platform-ui-home/rcp-proposal/rcp_tutorial/tutorial1.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (download) (as text) (annotate)
Thu Feb 19 18:26:11 2004 UTC (5 years, 9 months ago) by nick
Branch: MAIN
Changes since 1.3: +65 -2 lines
Latest from Ed
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<title>Rich Client Platform</title>
<link href="default_style.css" rel=stylesheet>
</head>

<body>

<div align="right">
  <font face="Times New Roman, Times, serif" size="2">Copyright © 2003-2004 Ed
  Burnette.</font>
  <table border="0" cellspacing="0" cellpadding="2" width="100%">
    <tbody>
      <tr>
        <td align="left" valign="top" colspan="2" bgcolor="#0080c0"><b><font face="Arial,Helvetica"><font color="#ffffff">Eclipse
          Article</font></font></b></td>
      </tr>
    </tbody>
  </table>
</div>
<div align="left">
  <h1 title="RCP Tutorial"><img src="images/Idea.jpg" align="middle" width="120" height="86"></h1>
</div>
<h1 align="center">Rich Client Tutorial Part 1 - Draft</h1>
<p class="summary">The Rich Client Platform (RCP) is an exciting new way to
build Java applications that can compete with native applications on any
platform. This tutorial is designed to get you started building RCP applications
quickly.</p>
<p><b>By Ed Burnette, SAS Institute Inc.</b><br>
<font size="-1">February 18, 2004 - Updated for 3.0M7, adding Troubleshooting section</font></p>
<p><i>Note that Eclipse 3 is undergoing constant change so the steps you need to
take, the APIs, and the results may vary slightly (or not so slightly) from this
description.</i></p>
<hr width="100%">
<h2>Introduction</h2>
<p>Try this experiment: Show Eclipse to some friends or co-workers who haven't
seen it before and ask them to guess what language it is written in. Chances
are, they'll guess VB, C++, or C#, because those languages are used most often
for high quality client side applications. Then watch the look on their faces
when you tell them it was created in Java, especially if they are Java
programmers.</p>
<p>Because of its unique open source license, you can use the technologies that
went into Eclipse to create your own commercial quality programs With previous
version of Eclipse, this was possible but difficult, especially when you wanted
to heavily customize the menus, layouts, and other user interface elements. That
was because the &quot;IDE-ness&quot; of Eclipse was hard-wired into it. Version
3 introduces the Rich Client Platform, which is basically a refactoring of the
fundamental parts of Eclipse's UI, allowing it to be used for non-IDE
applications.</p>
<p>If you want to cut to the chase and look at the code you can <a href="RcpTutorial.zip">download
the Eclipse project here</a>. Otherwise, let's take a look at how to construct
an RCP application.</p>
<h2><a name="section_1"></a> Getting started</h2>
<p>RCP applications are based on the familiar Eclipse plug-in architecture, (if
it's not familiar to you, see the references section). Therefore, you'll need to
create a plug-in to be your main program.
Select New &gt; Project &gt; Plug-in
Development &gt; Plug-in Project to bring up the Plug-in Project wizard. On the
subsequent pages, enter a Project name such as <b>org.eclipsepowered.rcptutorial1</b>,
indicate you want a Java project, and
enter a Plug-in Id (this should match the project name).
</p>
<p>
The generated plug-in class that you may be familiar with in previous
releases is no longer required in Eclipse 3.0.
You can still have one to hold global data if you like, but for this
example just remove it altogether to save a little space.
To do this, turn off the option that says
Generate the Java class that controls the plug-ins life cycle.
Then Click on Finish to
generate the template.</p>
<h2>The main program</h2>
<p>The main program for an application implements <code>IPlatformRunnable</code>,
which just has a method called
<code>run()</code>.
Listing 1 shows a simple implementation that shows you the minimum you have to
do.</p>
<p><b>Listing 1. RcpApplication class.
</b></p>
<pre>
package org.eclipsepowered.rcptutorial1;
import org.eclipse.core.boot.IPlatformRunnable;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.WorkbenchAdvisor;

public class RcpApplication implements IPlatformRunnable {
    public Object run(Object args) {
        WorkbenchAdvisor workbenchAdvisor = new RcpWorkbenchAdvisor();
        Display display = PlatformUI.createDisplay();
        int returnCode = PlatformUI.createAndRunWorkbench(display,
            workbenchAdvisor);
        if (returnCode == PlatformUI.RETURN_RESTART) {
            return IPlatformRunnable.EXIT_RESTART;
        } else {
            return IPlatformRunnable.EXIT_OK;
        }
    }
}
</pre>
<h2>Creating a default perspective</h2>
<p>
Next, you must define at least one perspective and make it the default.
Perspectives are created by implementing <code>IPerspectiveFactory</code> (see listing 2).
The important part
of this interface is the <code>createInitialLayout()</code> method where you position and
open any views and/or editors you'd like the user to start with.
In this example
we're not going to create any views so it will be a pretty boring perspective.
</p>

<p><b>Listing 2. RcpPerspective class.
</b></p>
<pre>
package org.eclipsepowered.rcptutorial1;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class RcpPerspective implements IPerspectiveFactory {

    public RcpPerspective() {
    }

    public void createInitialLayout(IPageLayout layout) {
    }
}

</pre>
<h2>Workbench Advisor</h2>
<p>
The Workbench Advisor class helps customize the workbench to add and subtract
toolbars, perspectives, and so forth.
This will covered in more detail in part 2 of the tutorial.
For now, the absolute minimum you have to do here
is define which perspective is the default one.
See listing 3 for the code.
</p>

<p><b>Listing 3. RcpWorkbenchAdvisor class.
</b></p>
<pre>
package org.eclipsepowered.rcptutorial1;
import org.eclipse.ui.application.WorkbenchAdvisor;

public class RcpWorkbenchAdvisor extends WorkbenchAdvisor {

    public String getInitialWindowPerspectiveId() {
        return &quot;org.eclipsepowered.rcptutorial1.RcpPerspective&quot;;
    }
}
</pre>
<h2>Plug-in manifest</h2>
<p>As usual, the plug-in manifest, plugin.xml, ties everything together.
The class name in
the plugin tag refers to the plug-in class we deleted earlier,
so you should remove the reference too.
The main program
class name is defined with the <code>org.eclipse.core.runtime.applications</code> extension
and the perspective with <code>org.eclipse.ui.perspectives</code>.
When you're done you should have something that looks like listing 4.
</p>

<p><b>Listing 4. Plugin.xml.
</b></p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;?eclipse version=&quot;3.0&quot;?&gt;
&lt;plugin
    id=&quot;org.eclipsepowered.rcptutorial1&quot;
    name=&quot;%pluginName&quot;
    version=&quot;0.0.0&quot;
    provider-name=&quot;%providerName&quot;&gt;

    &lt;runtime&gt;
        &lt;library name=&quot;rcptutorial1.jar&quot;&gt;
            &lt;export name=&quot;*&quot;/&gt;
        &lt;/library&gt;
    &lt;/runtime&gt;
    &lt;requires&gt;
        &lt;import plugin=&quot;org.eclipse.core.runtime.compatibility&quot;/&gt;
        &lt;import plugin=&quot;org.eclipse.ui&quot;/&gt;
    &lt;/requires&gt;


    &lt;extension
        id=&quot;RcpApplication&quot;
        point=&quot;org.eclipse.core.runtime.applications&quot;&gt;
        &lt;application&gt;
            &lt;run
                class=&quot;org.eclipsepowered.rcptutorial1.RcpApplication&quot;&gt;
            &lt;/run&gt;
        &lt;/application&gt;
    &lt;/extension&gt;
    &lt;extension
        point=&quot;org.eclipse.ui.perspectives&quot;&gt;
        &lt;perspective
            name=&quot;%perspectiveName&quot;
            class=&quot;org.eclipsepowered.rcptutorial1.RcpPerspective&quot;
            id=&quot;org.eclipsepowered.rcptutorial1.RcpPerspective&quot;&gt;
        &lt;/perspective&gt;
    &lt;/extension&gt;
&lt;/plugin&gt;
</pre>
<h2>Miscellaneous</h2>
<p>The build.properties file (see listing 5)
will be needed when exporting the application for
others to use.</p>

<p><b>Listing 5. Build.properties.
</b></p>
<pre>
bin.includes = plugin.xml,\
               *.jar,\
               rcptutorial1.jar,\
               plugin.properties
source.rcptutorial1.jar = src/
</pre>

<p>
Finally, the plugin.properties file (listing 6) contains natural language strings at the
plug-in registry level (i.e., things the run-time has to know about your plug-in
before even loading it).
You could hard-code these into your plug-in manifest
but it's best to get into the i18n habit from the start.
</p>

<p><b>Listing 6. Plugin.properties
</b></p>
<pre>
pluginName = RcpTutorial1 Plug-in
providerName = eclipsepowered.org
perspectiveName = RcpTutorial1
</pre>

<h2>Taking it for a spin</h2>
<p>Normally, when testing a plug-in you would select the project and then select
Run &gt; Debug &gt; Debug As &gt; Run-time Workbench. Go ahead and try that now.
It will give you a full blown Eclipse IDE Workbench window because we haven't
overridden the application name - it is still defaulting to the IDE application.
</p>
<p>
To fix this, edit the launch configuration you just created (select Run &gt;
Debug &gt; Debug..., and then select New_Configuration or create a new one). In
the Arguments tab, select <code>org.eclipsepowered.rcptutorial1.RcpApplication</code>
for the Application name.
This comes from the id specified on the
<code>org.eclipse.core.runtime.applications</code> extension point
(in this example, <code>RcpApplication</code>), prepended with the
plug-in id (<code>org.eclipsepowered.rcptutorial1</code>).
</p>
<p>Now switch over to the Plug-ins and Fragments tab. Select the option to
Launch with this plug-in and all of its pre-requisites.
Enter the plug-in id (<code>org.eclipsepowered.rcptutorial1</code>)
and press Debug. You should see a bare-bones Workbench start up (see figure 1).</p>

<p><b>Figure 1. World's simplest RCP application.
</b></p>
<img src="images/spin.png" width="404" height="270">

<p>If you don't see this, you should be able to find an error message in the
run-time workbench's .log file (runtime-workspace/.metadata/.log). Simply bring
it up in a text editor and look for the most recent errors. You may find it
useful to delete the .log file before running the program so you won't get
confused by older messages.</p>
<p>
<img src="images/tip.gif" alt="Tip: " width="62" height="13">
Specify the <code>-consoleLog</code> option
in the Arguments tab under Program Arguments to have all error messages
sent to the Console. This is easier than searching around for the .log file.
</p>

<h2>Running it outside of Eclipse</h2>
<p>The whole point of all this is to be able to run stand-alone applications
without the user having to know anything about the Java and Eclipse code being
used under the covers. For a real application you will probably want to provide
a self-contained executable generated by an install program like InstallShield.
That's really beyond the scope of this article though, so we'll do something
simpler.</p>
<p>We need to create a simplified version of the Eclipse install directory
because the Eclipse plug-in loader expects things to be in a certain layout.
Here are the steps to get started:</p>
<ol>
  <li>Right click on the plug-in project and select Export.
  <li>Select Deployable plug-ins and fragments and then press Next.
  <li>Select the plug-in(s) that should be included. For this
  example that would be org.eclipsepowered.rcptutorial1.
  <li>Select the option to Export as a directory structure, and for the
  directory enter a name ending with RcpTutorial1 (for example, C:\RcpTutorial1 on
  Windows).
  <li>If you want to provide source code for your application,
  select the Include Source Code option.
  <li>Press Finish to export the plug-in.
  Eclipse will perform a full build in the background
  and populate the directory for you.
</ol>
<p>To complete the RcpTutorial1 directory, copy the startup.jar file from the Eclipse
install directory into the top level, and copy all the org.eclipse plug-ins
that are required into the plugins directory.
</p>
<p>
Which ones are required, you ask?
You can find a partial answer by right-clicking on the project and selecting
PDE Tools > Open Dependencies.
Add all the plug-ins listed there, including all the ones they depend on (you can
see the list by fully expanding the tree).
</p>
<p>
In addition to these, you'll have to add any plug-ins that
are required at run-time but not at build time.
These may not be listed directly or indirectly in your plugin.xml file.
The only way to find them in current builds is to run the application
and see if it fails,
and add any required plug-ins until it stops failing.
Hopefully this will be improved in a future build.
See the Troubleshooting section for more information.
</p>
<p>
When you're
done you should have a structure that looks like this:</p>
<pre>
    RcpTutorial1
    |    startup.jar
    +--- plugins
         +--- org.eclipse.core.runtime.compatibility_3.0.0
         +--- org.eclipse.core.runtime_3.0.0
         +--- org.eclipse.help_3.0.0
         +--- org.eclipse.jface_3.0.0
         +--- org.eclipse.osgi.services_3.0.0
         +--- org.eclipse.osgi.util_3.0.0
         +--- org.eclipse.osgi_3.0.0
         +--- org.eclipse.swt.win32_3.0.0
         +--- org.eclipse.swt_3.0.0
         +--- org.eclipse.ui.workbench_3.0.0
         +--- org.eclipse.ui_3.0.0
         +--- org.eclipse.update.configurator_3.0.0
         +--- org.eclipsepowered.rcptutorial1
</pre>
<p>That's all you need to run an RCP application, but it would be difficult for
anyone to use it without some kind of launching program. Eclipse uses
eclipse.exe, but for this example we'll just use a batch file.
Create a Windows command file
called rcptutorial1.cmd and place it in the top level RcpTutorial1 directory. A Unix shell
script version would be similar.
<pre>
    @echo off
    setlocal
    cd %~dp0
    rem Check workspace\.metadata\.log for errors
    start javaw -cp startup.jar org.eclipse.core.launcher.Main
        -application org.eclipsepowered.rcptutorial1.RcpApplication %*
    endlocal

</pre>
<p>The start command should be all on one line. As before, the -application
option refers back to the id specified on the
org.eclipse.core.runtime.applications extension point.</p>
<p>You can get as fancy as you want in this script file. Here's a variant that I
like to use when debugging because it will display any error messages from the
Eclipse loader in a separate window:</p>
<pre>
    echo on
    setlocal
    cd %~dp0
    rem Display workspace\.metadata\.log if there are errors
    del workspace\.metadata\.log
    java -cp startup.jar org.eclipse.core.launcher.Main
        -application org.eclipsepowered.rcptutorial1.RcpApplication %*
        || type workspace\.metadata\.log &amp;&amp; pause
    endlocal
</pre>
<p>The java command should be all on one line.</p>
<p>To eliminate the startup window on Windows, you can use a shortcut instead of
a script file. Right click inside the RcpTutorial1 folder, select New &gt; Shortcut
and enter this as the location of the item (on one line):</p>
<pre>
    %windir%\system32\javaw.exe -cp startup.jar org.eclipse.core.launcher.Main
        -application org.eclipsepowered.rcptutorial1.RcpApplication
</pre>
<p>Enter a descriptive name on the next page and then press Finish. Then try
double-clicking on your new shortcut to try it out. You may want to edit the
shortcut (right click on it and select Properties) to change the default working
directory.</p>
<p>
<img src="images/tip.gif" alt="Tip: " width="62" height="13">
For fully branding a program with a splash screen, custom icons, and so forth
you'll need to define a primary feature, some configuration files, and use
the eclipse.exe launcher.
See the online help under Platform Plug-in Developer Guide >
Programmer's Guide > Packaging and delivering Eclipse based products
for more information.
</p>

<h2>Troubleshooting</h2>
<p>
After I wrote this tutorial I started getting mail from people who couldn't
run it for one reason or another.
This section will collect the errors that they've seen and
the solutions.
Remember to use the <code>-consoleLog</code> command line option to see
extra diagnostics in the console window where you invoked your
RCP application.
</p>
<dl>
<dt>
<b>Launching failed because the following plug-ins are neither in the
workspace nor selected on the Target Platform preference page: ...</b>
<dd>
This one is a sanity check performed by PDE.
It's pretty self explanitory so just look at the list
provided, go to the Plug-ins tab of your launch configuration,
and put a checkmark next to all of the plug-ins listed
in the error.

<dt>
<b>!MESSAGE Unable to locate application extension: org.eclipsepowered.rcptutorial1.RcpApplication</b>
<dd>
First, check to make sure that the plug-in containing your
application is included in your launch configuration.
Next, check the spelling, and remember that the application name
is the plug-in id followed by a period and the id you specified on the
<code>org.eclipse.core.runtime.applications</code> extension.
This message might also be printed if all the required
plug-ins are not available at run-time (though in M7 and later
you're supposed to get a different error for this case).
<dt>
<b>!MESSAGE Bundle reference:file:C:/eclipse/plugins/org.eclipse.ui_3.0.0 [13] was not resolved</b>
<dd>
This one is a little tougher.
It usually means that some prerequisite of the plug-in listed was not there
You can find out exactly what's going on by re-running the program
with the <code>-console</code> command line option.
This will allow you to enter OSGi console commands to diagnose the problem.
After the error occurs again, go to the console window and enter the
<code>ss</code> command.
You'll see one or more bundles which were installed but not resolved.
Pick one of them (in the above message it would be number 13), and enter the
<code>diag <i>nnn</i></code> command, where <i>nnn</i>
is the bundle number. For example, "<b>diag 13</b>".
This will tell you what the missing bundle is.
Note that you can't run OSGi commands if the program has already terminated.
Future builds will have better error messages so you don't have to
go through all this - they'll just tell you what's missing.
</dl>


<h2>Conclusion</h2>
<p>In part 1 of this tutorial, we looked at what is necessary to create a
bare-bones Rich Client application. The next part will delve into customizations
using the WorkbenchAdvisor class.
All the sample code may be <a href="RcpTutorial.zip">downloaded
here</a>.
</p>

<h2>References</h2>
<p><a href="../rich_client_platform_facilities.html">Rich Client Platform
Facilities</a><br>
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36967">Bug 36967 - [Plan
Item] Enable Eclipse to be used as a rich client platform</a><br>
<a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.ui.examples.rcp.browser/readme.html">RCP Browser example
(project org.eclipse.ui.examples.rcp.browser)</a><br>
<a href="http://www.eclipse.org/articles/Article-PDE-does-plugins/PDE-intro.html">PDE
Does Plug-ins</a><br>
<a href="http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html">How
to Internationalize your Eclipse Plug-in</a><br>
<a href="http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html">Notes
on the Eclipse Plug-in Architecture</a><br>
</p>
<p><small>IBM is trademark of International Business Machines Corporation in the
United States, other countries, or both.</small></p>
<p><small>Java and all Java-based trademarks and logos are trademarks or
registered trademarks of Sun Microsystems, Inc. in the United States, other
countries, or both.</small></p>
<p><small>Microsoft and Windows are trademarks of Microsoft Corporation in the
United States, other countries, or both.</small></p>
<p><small>Other company, product, and service names may be trademarks or service
marks of others.</small></p>

</body>

</html>