März 28, 2011

The last days I need to create a small prototype to demonstrate how to start a eclipse RCP application via webstart. After reading many tutorials and tipps I have now a working setup which I want to share with you.

The main tutorial which I followed was the eclipse help itself. But there are some hidden points which are important to respect.

This plugin will provide the RCP application with a small demo UI. In a larger project you will normally have more than one plugin. But for demonstration proposed this would be enough.

From the eclipse main menu, go to File > New > Project… (the New Project wizard opens), select Plugin-in Development > Plug-in Project

Press Next > enter „org.test.webstart.demo.plugin“ as Project name

Press Next > change the Version to „0.1.0“

Press Next > select RCP application with an view > press Finish

At this point you should have a small RCP „application“ which can started from eclipse. Select the project root > select Run from the menu > select Run As > Eclipse Application. Now you should see the demo UI.

Next we need a Eclipse feature project which uses the plugin.

Create eclipse feature which contains the plugin and a reference to the eclipse rcp feature:

We need a feature which depends on the demo plugin and on the eclipse rcp feature. The dependency to the eclipse rcp feature is required to export later all required plugins and features for webstart, to run the complete rcp application.

In the eclipse main menu go to File > New > Project… (the New Project Dialog opens), select Plug-in Development > Feature Project

Press Next > enter „org.test.webstart.demo.feature“ as project name > change the Version to „0.1.0“

The feature editor opens. Now you need to add the eclipse rcp feature as included feature. To do so select Included Feature tab in the feature editor > add „org.eclipse.rcp“ as feature. Save and close the feature editor.

This feature contains now all you need to run your application as a full featured eclipse RCP application. Now we need another wrapping feature to get the Webstart launcher on board.

Create wrapping feature for webstart

This feature will be used to export all required JAR files with the eclipse java webstart exporter into a local filesystem.

From the eclipse main menu select File > New > Project… (the New Project Dialog opens), select Plug-in Development > Feature Project

Press Next > enter „org.test.webstart.demo.wrapperfeature“ as project name > change the Version to „0.1.0“

Press Finish. The feature editor opens.

Now we need a dependency to the equinox launcher plugin and include our own feature.

As a final step you need to create your entry JNLP file which is the starting point of your webstart application. Here is an example for start.jnlp:

<?xml version="1.0" encoding="UTF-8"?>
<jnlp
spec="1.0+"
codebase="http://localhost:8080/demoui-webstart"
href="start.jnlp">
<information>
<!-- user readable name of the application -->
<title> Demo UI Application </title>
<!-- vendor name -->
<vendor>Me</vendor>
<!-- vendor homepage -->
<homepage href="http://www.me.org" />
<!-- product description -->
<description>description</description>
<offline-allowed/>
</information>
<!--request all permissions from the application. This does not change-->
<security>
<all-permissions/>
</security>
<!-- The name of the main class to execute. This does not change-->
<application-desc main-class="org.eclipse.equinox.launcher.WebStartMain">
<argument>-nosplash</argument>
</application-desc>
<resources>
<!-- Reference to the launcher jar. The version segment must be updated to the version being used-->
<jar href="plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar"/>
<!-- Reference to all the plugins and features constituting the application -->
<!-- Here we are referring to the wrapper feature since it transitively refers to all the other plug-ins necessary -->
<extension
name="Wrapper feature"
href="features/
org.test.webstart.demo.wrapperfeature_0.1.0.jnlp"/>
<!-- Information usually specified in the config.ini -->
<property
name="osgi.instance.area"
value="@user.home/Application Data/demoui-rcp"/>
<property
name="osgi.configuration.area"
value="@user.home/Application Data/demoui-rcp"/>
<!-- The id of the product to run, like found in the overview page of the product editor -->
<property
name="eclipse.application"
value="org.demo.webstart.plugin.application"/>
</resources>
<!-- Indicate on a platform basis which JRE to use -->
<resources os="Windows">
<j2se version="1.5+"/>
</resources>
<resources os="Linux">
<j2se version="1.5+"/>
</resources>
</jnlp>

Some remarks according the main JNLP file:

You need to adjust (or take care) of the lines 04, 30, 36, 48.

Line 04 defines the codebase. Every time you want to deploy you application on an websever you need to adjust the codebase (in every JNLP file in your project!) to the web application location.

Line 30 depends on you eclipse distribution (I have used eclipse 3.5 with some updates). You have to check the right version in your plugins folder and update the start.jnlp file.

Line 36 defines the starting feature JNLP file. This file itself refers to the other JNLP files in the features folder (which is automatically done from the eclipse exporter). You need to adjust this line if your project name differs from this example.

Line 48 defines the entry point to your application. This is the application ID from the example plugin. You can find the ID if you open the plugin editor of your example plugin. To do so open your example plugin and open the plugin.xml file. Under the tab Overview you can find the ID: „org.demo.webstart.plugin“. Now you also need to open the tab Extensions. Under the Extensions Details you can find the ID of your application. The complete application ID which you need to refer in the JNLP file is then „org.demo.webstart.plugin.application“.

If you now put the main JNLP file and the plugins + features folders under an webserver which delivers the files from http://localhost:8080/demoui-webstart/ you can see your test application. You should have following structure:

Hint:
A small problem over which I stumbled while developing the example application:

If you start the application and you get from webstart an exception that plugin with *WTP* are not found, you can have a look into the JNLP files in the features folder. Some of these files define resources which are not exported by the eclipse webstart exporter. I have simple removed these resources from the JNLP files and it works.

Update:
I have created a Github repository with some code examples. You may clone my repo or send me patches with corrections.

September 7, 2010

As anybody knows I’am a Co-developer for the last years for a Java based EMail client called Columba. Now the program was honoured by the big german IT magazin Heise.

The last moths, there are no more many code changes in the project and I can say the project is dead (from the developer point of view). I have learned many about open source programming, Java coding and got new friends in this project. It was very funny to work on this EMail client!

Now we got after many years good feedback for our work and it is nice to see that the project still have users which are like this kind of EMail client.

August 21, 2009

On my work we develop eclipse plugins and want to add the current bundle id and bundle version to the since field for class comments. There are not much examples around this problem (we have searched google and eclipse help) so let me explain how you can achive this.

The bundleId and bundleVersion variable are not provided by the standard code template variables. Now we have to find out how we can achive this problem.

First of all you need to develop your own eclipse plugin which should provide such feature. The new plugin requires follow dependencies:

org.eclipse.core.resources;bundle-version=“3.5.0″,

org.eclipse.ui;bundle-version=“3.5.0″,

org.eclipse.jface.text;bundle-version=“3.5.0″,

org.eclipse.jdt.core;bundle-version=“3.5.0″,

org.eclipse.jdt.ui;bundle-version=“3.5.0″,

org.eclipse.core.runtime;bundle-version=“3.5.0″,

org.eclipse.pde.core;bundle-version=“3.5.0″

The PDE dependency is needed to get the current bundle id and the bundle version. If you need other features (for example a maven project version) you have depend on other plugins. But in this example I’ll show you how to add bundle id and bundle version as extra variable for the eclipse code templates.

Next you have to create a extention to register your own variable resolver at startup. The variable resolvers are the heart of the plugin because they providing new variables for the code templates to be used and resolving the content if you use the code template.

The RegisterResolvers class implements the IStartup interface from eclipse. This class registers the variable resolvers to the code template context. This is required to have the variables available in the code templates from eclipse.

The bundleIdResolver extends the TemplateVariableResolver and defines (in the default constructor) the variable name which can be used later in the code template, a description and overrides the resolve method.

The resolve method checks if the current project is a plugin project and if so returns the bundle id from the project.

Now you can come up with the question why not you can use the standard eclipse extention point mechanism and create your own context.

Well, we want to extend the java context but the current eclipse implementation doe’s not provide such functionality. For sure if you want to have your own context you can do this with the standard extention point mechanism (as the Ant example). There is a small example about the eclipse editor templates.

November 28, 2008

There are not much examples, how to use a ELExpression from your java code. The most examples I found, are focussing on „implement your own ELResolver“. The best documentation comes from SUN in form of tutorials and package/javadoc.

Now I will provide some tips how to deal with EL expressions from java. I have tested and implemented this in a JSF 1.2 web application, where I have access to the FacesContext.

Now you can use the expression factory to get a MethodExpression or ValueExpression. In my projects we need very often ValueExpressions.

But first you need also an ELContext. There are many implementations available of such context (for JSP, Faces and so on) and enough documentation how to create your own context.
You can access such context again from the faces context:

In this example I will use the boolean value from a „devBean“ to work later with this value. Of course, you can inject the value expression, required class type and so on.
The last needed thing is to assign the value to a local variable:

September 9, 2008

Sometimes you will select a tree node in a richfaces tree, triggered by your datamodel. There are several hints how to do this with a tree state advisor, but I have found another way to do this.

My main problem was, that I do not have a relation between my datamodel and the richfaces UITree components (nodes). This problem was introduced because I use the recursiveTreeAdaptor. I have not found a way to get a TreeRowData object from the UITree for my datamodel object.

I have searched in the richfaces implementation, if there is another way to work with my datamodel which have to expand the tree, if the datamodel is changed.

Lets clearify what I want to do: I have a datamodel with some root nodes and „normal“ nodes in a tree like structure. I have also (in my TreeManager) a parameter which holds a selectedNode. A node can selected from the UI (the user clicks on a tree node and causes a node selection event) or from my datamodel, which calls a method in the TreeManager to select a specific tree node.

The tree manager contains a method to select a specific node like this:

The tree walk method walks over the tree using my own data visitor and tree range. The tree range implementation tolds the tree to walk also over hidden nodes. You remember? The tree should expand all nodes to the selected node, also if the selected node is hidden.

You can queue node expanding with a tree rowKey to the node, which you want to expand. You don’t need to queue all nodes on the path. The queueNodeExpand method works fine with one rowkey. The row describes itself the complete path to the node. If you use standard jsf ID’s, a possible treeRowKey looks like „jsp123:jsp124:jsp125“ wich is the complete path to your node (row key).

You have to know, that you don’t want expand the selected node (this is in most cases a leafe). You want to expand the tree to the parent of the selected node.

Normally you can use theTree.getTreeNode(); but with a recursive tree model which method returns alway null. Instead of this I have used the getRowData() method which works for me.
I have filed a bug for richfaces. Hope the problem becomes shortly a solution.