Create a “Hello World” Eclipse RAP application with OSGi and Bndtools

The Eclipse Remote Application Platform is an Eclipse project for enabling RCP application for the web or mobile usage. It can be used in OSGi or Servlet containers such as JEE.

There is a good tooling based on the Eclipse tooling. We got a request from a customer, if it is in general possible to realize RAP development using Bndtools and the Gradle build for RAP development.

As we know now, the answer is: “Yes, and its not that hard”

We gave it a try using the “Hello World” application from the RAP documentation [2] using bndtools.

At first we need to add all the dependencies to the build.bnd. A very good thing is, that you can find the JAR’s for version 3.9 RAP dependencies at Maven Central. So, you just need to add a Maven repository to your build.bnd:

-plugin.Central: \      
    aQute.bnd.repository.maven.provider.MavenBndRepository; \            		             releaseUrl=https://repo.maven.apache.org/maven2/; \      
    index=${.}/central.maven; \       
    name="Maven Central"

In the central.maven index file you can add all dependencies:

org.eclipse.rap:org.eclipse.rap.rwt:3.9.0 org.eclipse.rap:org.eclipse.rap.rwt.osgi:3.9.0 org.eclipse.rap:org.eclipse.rap.ui:3.9.0 org.eclipse.rap:org.eclipse.rap.ui.forms:3.9.0 org.eclipse.rap:org.eclipse.rap.ui.views:3.9.0 org.eclipse.rap:org.eclipse.rap.ui.workbench:3.9.0 org.eclipse.rap:org.eclipse.rap.filedialog:3.9.0 org.eclipse.rap:org.eclipse.rap.fileupload:3.9.0 org.eclipse.rap:org.eclipse.rap.jface:3.9.0 org.eclipse.rap:org.eclipse.rap.jface.databinding:3.9.0 org.apache.felix:org.apache.felix.scr:2.1.14 org.apache.felix:org.apache.felix.gogo.command:1.0.2 org.apache.felix:org.apache.felix.gogo.runtime:1.1.0 org.apache.felix:org.apache.felix.gogo.shell:1.1.0 org.apache.felix:org.apache.felix.http.jetty:4.0.6 org.apache.felix:org.apache.felix.http.servlet-api:1.1.2

In addition to that you also need some Eclipse dependencies. You can either use the P2 repository declaration in the build.bnd for that:

-plugin.photon: \    
    aQute.bnd.repository.p2.provider.P2Repository; \    
    url = https://download.eclipse.org/releases/photon/; \    
    name = "Photon"

Now after some download time, we can write some code. We should create a component project. For this you can use the corresponding project template from bndtools. We needs a service that is of type ApplicationConfiguration to create a RAP application.

package bnd.rap; 

import org.eclipse.rap.rwt.application.Application; 
import org.eclipse.rap.rwt.application.ApplicationConfiguration; 
import org.eclipse.rap.rwt.application.EntryPointFactory; 
import org.eclipse.rap.rwt.internal.lifecycle.DefaultEntryPointFactory; 
import org.osgi.service.component.annotations.*; 

@Component(immediate = true) 
public class Example implements ApplicationConfiguration {     
    @Override    
    public void configure(Application application) {        
        EntryPointFactory epf = new DefaultEntryPointFactory(MyEntryPoint.class);                 application.addEntryPoint("/testrap", epf, null);    
    } 

}

As you see, we need an EntryPoint implementation, that is then created from the DefaultEntryPointFactory.

package bnd.rap; 

import org.eclipse.rap.rwt.application.AbstractEntryPoint; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Button; 
import org.eclipse.swt.widgets.Composite; 

public class MyEntryPoint extends AbstractEntryPoint {     
    
    @Override    
    protected void createContents(Composite parent) {        
        parent.setLayout(new GridLayout(2, false));        
        Button checkbox = new Button(parent, SWT.CHECK);        			                     checkbox.setText("Hello");        
        Button button = new Button(parent, SWT.PUSH);        
        button.setText("World");    } 
    
}

Now we need a bndrun configuration to start everything. As OSGi framework we use org.eclipse.osgi. In addition to that we needs some run requirements. We use the org.apache.felix.http.jetty as implementation for a servlet container. You can find the dependencies on maven central as well. Taking all the -runrequires from below, you can then resolve you dependencies. This may take a while. After that, you get a similar -runbundles result.

-runprovidedcapabilities: ${native_capability} -resolve.effective: active;skip:="osgi.service" -runbundles: \    bnd.rap;version=snapshot,\    org.apache.felix.gogo.command;version='[1.0.2,1.0.3)',\    org.apache.felix.gogo.shell;version='[1.1.0,1.1.1)',\    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\    org.apache.felix.scr;version='[2.1.14,2.1.15)',\    org.apache.felix.http.jetty;version='[4.0.6,4.0.7)',\    com.ibm.icu;version='[58.2.0,58.2.1)',\    org.apache.commons.fileupload;version='[1.3.2,1.3.3)',\    org.apache.commons.io;version='[2.2.0,2.2.1)',\    org.apache.felix.gogo.runtime;version='[1.0.6,1.0.7)',\    org.eclipse.core.commands;version='[3.9.100,3.9.101)',\    org.eclipse.core.contenttype;version='[3.7.0,3.7.1)',\    org.eclipse.core.databinding;version='[1.6.200,1.6.201)',\    org.eclipse.core.databinding.observable;version='[1.6.200,1.6.201)',\    org.eclipse.core.databinding.property;version='[1.6.200,1.6.201)',\    org.eclipse.core.expressions;version='[3.6.100,3.6.101)',\    org.eclipse.core.jobs;version='[3.10.0,3.10.1)',\    org.eclipse.core.runtime;version='[3.14.0,3.14.1)',\    org.eclipse.equinox.app;version='[1.3.500,1.3.501)',\    org.eclipse.equinox.common;version='[3.10.0,3.10.1)',\    org.eclipse.equinox.http.registry;version='[1.1.500,1.1.501)',\    org.eclipse.equinox.preferences;version='[3.7.100,3.7.101)',\    org.eclipse.equinox.registry;version='[3.8.0,3.8.1)',\    org.eclipse.help;version='[3.8.100,3.8.101)',\    org.eclipse.osgi.services;version='[3.7.0,3.7.1)',\    org.eclipse.rap.filedialog;version='[3.5.0,3.5.1)',\    org.eclipse.rap.fileupload;version='[3.5.0,3.5.1)',\    org.eclipse.rap.jface;version='[3.5.0,3.5.1)',\    org.eclipse.rap.jface.databinding;version='[3.5.0,3.5.1)',\    org.eclipse.rap.rwt;version='[3.5.0,3.5.1)',\    org.eclipse.rap.rwt.osgi;version='[3.5.0,3.5.1)',\    org.eclipse.rap.ui;version='[3.5.0,3.5.1)',\    org.eclipse.rap.ui.forms;version='[3.5.0,3.5.1)',\    org.eclipse.rap.ui.views;version='[3.5.0,3.5.1)',\    org.eclipse.rap.ui.workbench;version='[3.5.0,3.5.1)',\    org.osgi.util.function;version='[1.1.0,1.1.1)',\    org.osgi.util.promise;version='[1.1.0,1.1.1)' -runrequires: \    osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.shell)',\    osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)',\    bnd.identity;id='bnd.rap',\    bnd.identity;id='org.eclipse.rap.jface',\    bnd.identity;id='org.eclipse.rap.rwt.osgi',\    bnd.identity;id='org.eclipse.rap.ui',\    bnd.identity;id='org.eclipse.rap.ui.forms',\    bnd.identity;id='org.eclipse.rap.ui.views',\    bnd.identity;id='org.eclipse.rap.ui.workbench',\    bnd.identity;id='org.eclipse.rap.filedialog',\    bnd.identity;id='org.apache.felix.http.jetty' -runfw: org.eclipse.osgi;version='[3.13.100.v20180827-1536,3.13.100.v20180827-1536]' -runee: JavaSE-1.8 -runvm: -Dorg.osgi.service.http.port=8082

Now the application is ready to run. In that case we launch the servlet container on port 8082. The RAP application can now be reached at http://localhost:8082/testrap.

This was easy, wasn’t it?

[1] https://www.eclipse.org/rap/

[2] https://www.eclipse.org/rap/developers-guide/devguide.php?topic=hello-world.html&version=3.9

[3] https://bndtools.org/

by Ilenia Salvadori, Mark Hoffmann, Jürgen Albert