Lightweight OSGi Applications using RAP’s Widget Toolkit

Update 2: The new interfaces have been renamed again in RAP 1.5M7. Please refer to this post for the details and check out the updated code example.

Update: APIs have changed a bit meanwhile, so I updated the code below accordingly. Entry points are now registered by path, and JEE_COMPLATIBILTIY has become the default mode, which makes the main loop obsolete in this kind of applications.

RAP is well known as an “RCP for the web browser”, including workbench, extension points, and all that stuff. Indeed, one of the greatest features of RAP is its ability to reuse RCP code in web applications. But did you know that you can also use RAP’s widget toolkit (RWT) to create simple web UIs for your applications, without the heavy weight Eclipse UI stack?

With RAP 1.5, you can now simply include RWT in any OSGi application. You only need two bundles: org.eclipse.rap.rwt (the RAP widget toolkit itself) and org.eclipse.rap.rwt.osgi which integrates RWT with the OSGi HTTP service. There are no tie-ins with Equinox anymore, thus RAP also works with other OSGi containers.

To create a UI with RWT, you have to implement the interface IEntryPoint, here’s a simple example:

  public int createUI() {
    // Create a maximized top-level shell without trimmings that represents the main "page"
    Display display = new Display();
    Shell page = new Shell( display, SWT.NO_TRIM );
    page.setMaximized( true );
    page.setLayout( new GridLayout() );
 
    // Create contents of main shell
    Label label = new Label( page, SWT.NONE );
    label.setText( "Hello" );
    Button button = new Button( page, SWT.PUSH );
    button.setText( "World" );
 
    // Open the top-level shell and run the main loop to process events
    page.layout();
    page.open();
    return 0;
  }

Now what’s new is that, instead of registering this entry point with an extension point, you can now implement the new ApplicationConfigurator interface like this:

  public void configure( Context context ) {
    context.addEntryPoint( "/simple", SimpleEntryPoint.class );
    context.addBranding( new AbstractBranding() {
      @Override
      public String getServletName() {
        return "simple";
      }
      @Override
      public String getTitle() {
        return "Simple RWT Example";
      }
    } );
  }

When this implementation is registered as an OSGi service, you can access the UI with a web browser:

RWTSimple Lightweight OSGi Applications using RAPs Widget Toolkit

You can check out the example project example.rwt.simple from my rap-helpers repository on github. Please note that for this example to run you need declarative services in your target platform, which are not included in the RAP 1.5M1 target but in the latest nightly build. Also be aware that the new API is still provisional and may change again until the final release.

Kudos to Frank Appel, who contributed the new OSGi integration. He has a more detailed introduction to the new OSGi integration and examples for configuration in his blog. BTW, Frank and me plan to demo the possibilities of this approach in our talk Dynamic web applications with OSGi and RAP at the EclipseCon Europe – vote for it if you’re interested!

7 Responses to “Lightweight OSGi Applications using RAP’s Widget Toolkit”

  1. Josen says:

    I did all the steps except I am using 1.5M1 and registering the service manually.

    context.registerService( Configurator.class.getName(), new SimpleConfigurator() , null );

    And I get the following error:

    RequestURI=/simple

    Caused by:

    java.lang.IllegalStateException: No ApplicationContext registered.
    at org.eclipse.rwt.internal.engine.ApplicationContextUtil.checkApplicationContextExists(ApplicationContextUtil.java:114)
    at org.eclipse.rwt.internal.engine.ApplicationContextUtil.getInstance(ApplicationContextUtil.java:79)
    at org.eclipse.rwt.internal.engine.RWTFactory.getServiceManager(RWTFactory.java:47)
    at org.eclipse.rwt.internal.engine.RWTDelegate.handleValidRequest(RWTDelegate.java:62)
    at org.eclipse.rwt.internal.engine.RWTDelegate.doPost(RWTDelegate.java:41)
    at org.eclipse.rwt.internal.engine.RWTDelegate.doGet(RWTDelegate.java:33)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.eclipse.rap.rwt.osgi.internal.CutOffContextPathWrapper.service(CutOffContextPathWrapper.java:105)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    at org.ops4j.pax.web.service.internal.HttpServiceServletHandler.handle(HttpServiceServletHandler.java:66)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    at org.ops4j.pax.web.service.internal.HttpServiceContext.handle(HttpServiceContext.java:108)
    at org.ops4j.pax.web.service.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:64)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:320)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

  2. Frank says:

    Hi Josen,

    I just checked out the example.rwt.simple project from Ralf and removed the simpleconfiguration.xml from the manifest and replaced it by an Activator registration that looks like this:

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: RWT OSGi Example
    Bundle-SymbolicName: example.rwt.simple
    Bundle-Version: 1.0.0.qualifier
    Bundle-ActivationPolicy: lazy
    Bundle-RequiredExecutionEnvironment: J2SE-1.5
    Require-Bundle: org.eclipse.rap.rwt;bundle-version=”1.5.0″
    Bundle-Activator: rwt.simple.Activator
    Import-Package: org.osgi.framework;version=”1.6.0″

    public class Activator implements BundleActivator {

    public void start( BundleContext context ) throws Exception {
    context.registerService( Configurator.class.getName(), new SimpleConfigurator() , null );

    }

    public void stop( BundleContext context ) throws Exception {
    // TODO Auto-generated method stub

    }
    }

    Starting the included launch configuration with the latest nightly build did not show up any problem at all. Maybe you can use the implementation I provided above and look if the problem persists?

    Cheers
    Frank

  3. Josen says:

    Hi,

    Thanks for your help.

    It looks like it cannot be just any HttpService impl, or jetty. I was using pax webservices. I solve the problem by using the exact versions from the readme:

    0 ACTIVE org.eclipse.osgi_3.8.0.v20110726-1606
    1 ACTIVE org.eclipse.rap.rwt_1.5.0.201108131707
    2 ACTIVE org.eclipse.osgi.services_3.3.0.v20110711-1243
    3 ACTIVE org.mortbay.jetty.server_6.1.23.v201012071420
    4 ACTIVE javax.servlet_2.5.0.v201103041518
    5 ACTIVE org.eclipse.equinox.http.jetty_2.0.100.v20110502
    6 ACTIVE org.mortbay.jetty.util_6.1.23.v201012071420
    7 ACTIVE org.eclipse.equinox.util_1.0.300.v20110502
    8 ACTIVE org.eclipse.equinox.http.servlet_1.1.200.v20110502
    9 ACTIVE example.rwt.simple_1.0.0.qualifier
    10 ACTIVE org.eclipse.rap.rwt.osgi_1.0.0.201108131707
    11 ACTIVE org.eclipse.equinox.ds_1.3.100.v20110705

  4. Josen says:

    Hello,

    With this new approach, is it possible to have perspectives and views?

    How would this code look now? Is there a replacement for PlatformUI?

    Display display = PlatformUI.createDisplay();
    WorkbenchAdvisor advisor = new ApplicationWorkbenchAdvisor();
    return PlatformUI.createAndRunWorkbench( display, advisor );

  5. Ralf Sternberg says:

    Hi Josen,

    the whole idea of this approach is to enable “lightweight” RAP applications, i.e. without the workbench, the eclipse core bundles, the extension registry, all the things the workbench needs. If you want to write a workbench application, you have to include the extension registry, and you have to register an application. Actually, the RAP workbench uses the same mechanism internally.

    The approach presented here is suitable for user interfaces that use only SWT, and maybe JFace. If you are asking for a lightweight replacement for the workbench, then yes, I fully agree there should be such a thing. We have ideas to provide such a lightweight UI framework for the next major version, RAP 2.0.

    Regards, Ralf

  6. Paul Ramsden says:

    http://localhost:8080/rwt didn’t work for me (as described in the README) so I used http://localhost:8080/simple which is ok

  7. Ralf Sternberg says:

    Hi Paul,

    Yes, /simple is the correct URL (as set in the configurator). I fixed this in the README file. Thanks for pointing this out!

    Regards, Ralf

7 responses so far

Written by . Published in Categories: Planet Eclipse, Planet OSGi