Eclipse Yoxos Services Downloads Blogs About
Home > Blogs >

Archive for the ‘OSGi’ Category

on Jan 28th, 2012Lending a hand with the Eclipse SDK

Shipping Eclipse each year is a lot of work. The SDK contains code from 3 Top level projects (Eclipse, RT and Tools (Orbit)). There are 4+ Products (Platform, JDT, PDE , Equinox + Releng) and close to 20 Components (SWT, Text, UI, UA, etc…).  Once the SDK is built, the release train starts bolting on other projects (Mylyn, EGit, CDT, Birt, WPT, etc..).  Getting all these bits in the right place at the right time isn’t easy (although Kim and David sure makes it look easy).

While some teams are actively working on their components, other components are very mature and simply need some TLC from time-to-time.  There is certainly a number of things we could do with p2, but for the most part it works very well.  Pascal has been donating much of his personal time to p2 in order to give it the TLC and polish it needs. Pascal is pretty smart and 10 minutes of his time equates to an hour for most people icon smile Lending a hand with the Eclipse SDK .  However, it’s not fair that he spends all his free time tracking down problems in order for p2 to makes its contribution to the SDK.

EclipseRT Logo Medium Lending a hand with the Eclipse SDK

I’m happy to say that I’ll be helping Pascal co-lead the p2 project.  There’s a few things I have planned including

  1. Fixing a few recent problems on Java 7 Runtimes
  2. Improving the performance of the UI
  3. Looking at how we can reduce the size of our metadata (content.jar)

I’ll also be presenting some p2 related work at EclipseCon.  If you have questions, I try to hang around IRC and I’m also on twitter (@irbull).

on Jan 23rd, 2012An OSGi JAX-RS connector Part 1: Publishing REST services

In a recent blog post Peter Kriens commented that the OSGi service model is as important as object-orientation. I feel the same – I don’t want to write software without this concept anymore. But for me, the service model only makes sense when it’s used together with the modularity OSGi provides. I think the modularisation layer is the greatest advantage of the OSGi platform and the services are really only there to simplify the communication between modules.

When it comes to developing a REST API with Java, this advantage is missing in most of today’s libraries (e.g. Restlet or Jersey), because the Java language still lacks modularity. But especially for the design of a REST API this concept can be a great benefit, because it overcomes the limitation of only being able to separate REST services by url and Java packages. With modularity the service implementations can be separated into modules which improves the maintainability and the beauty of the whole system a lot.

A few months ago I discovered JAX-RS for developing REST services. (Before that I used Restlet.) I have to say that the JAX-RS API makes it really easy to develop REST services. See this article for a how-to. A reference implementation of this API is Jersey. The cool thing about this implementation is that it plays really well together with the OSGi HttpService and it ships as bundles. In this way we have the option to actively deploy REST services into the HttpService. But is this how we want to publish REST services? To me, it’s not!

In my ideal world I would write my @Path annotated Pojos and publish them as OSGi services. That’s it. The runtime should take care of publishing and service wiring. Sadly, Jersey has no built-in feature for that. This is the reason I wrote a little OSGi-JAX-RS connector. The only thing the connector does is that it publishes OSGi services as REST services using JAX-RS. Of course, there are OSGi remote services, but using them does not allow the use of JAX-RS the way I’d prefer, namely as a lightweight additional bundle.

You can find the connector in GitHub. To make it work simply install it into your OSGi instance by using this jar. (You’ll also find a p2 repository there). That’s it. The only thing you have to take care of is writing the REST services like the one in this example.

@Path( "/osgi-jax-rs" )
public class ExampleService {
 
  @GET
  public String seyHello() {
    return "JAX-RS and OSGi are a lovely couple.";
  }
}

The activator can then look like this:

public class Activator implements BundleActivator {
 
  private ServiceRegistration<?> registration;
 
  @Override
  public void start( BundleContext context ) throws Exception {
    ExampleService exampleService = new ExampleService();
    registration = context.registerService( ExampleService.class.getName(), exampleService, null );
  }
 
  @Override
  public void stop( BundleContext context ) throws Exception {
    registration.unregister();
  }
}

Further instructions can be found in the README of the git repository. It also contains two examples for using this connector with and without declarative services. In the second part of this blog series I will show you how to configure the services using the OSGi Configuration Admin Service and publish services on different ports within the same OSGi instance. I hope you enjoy this connector as much as I do.

followme An OSGi JAX RS connector Part 1: Publishing REST services

on Nov 14th, 2011Introducing restfuse – a JUnit Extension to test REST APIs

For several projects at EclipseSource we are creating REST APIs. I’m involved in most of them and there is one thing that bothers me with every project. That is, testing. I mean, of course we are writing our unit tests first and we mock our services to get fast unit tests, but at some point you also have to make sure that the whole system works with integration tests. And, when writing integration tests for REST APIs in Java, as far as I know, there are currently only two solutions.

The first one is to write plain JUnit tests and do all the requests yourself within the test methods (maybe with the help of utilities). The other option is to use a library called rest-assured. This library provides a kind of DSL for testing REST APIs. You can write your tests with JUnit and use mockito-like syntax to send a request and test the response. But this doesn’t feel like the right solution, because you always have to configure your request with real Java code within your test method. I would prefer a solution where I can simply configure the request using something like annotations and just execute the test after the request is sent.

Another thing that bugs me are asynchronous services. When it comes to handling asynchronous services you always have two options: callbacks or polling. How can I test those services? For polling it’s easier – you can loop the request code – but does this sound right to you? For callbacks you have to open a server, again within your test method or before. It seems there are no cool solutions for this right now – even rest-assured can’t handle these services very well. That’s why I took a little time and tried to solve these problems. The result is a small library called restfuse.

Restfuse is a JUnit extension. It introduces an annotation called @HttpTest which can be used to configure a request. The request is sent before the annotated method is executed as a test method. The response is then injected into the test object and can be used within the test method. It also provides some new asserts like assertNotFound or assertOk to test response codes. A simple @HttpTest looks like this:

@RunWith( HttpJUnitRunner.class )
public class RestfuseTest {
 
  @Rule
  public Destination destination = new Destination( "http://restfuse.com" ); 
 
  @Context
  private Response response; // will be injected after every request
 
  @HttpTest( method = Method.GET, path = "/" )
  public void checkRestfuseOnlineStatus() {
    assertOk( response );
  }  
}

And of course, it also solves the problem with asynchronous services by introducing two annotations called @Callback and @Poll which can be used together with the @HttpTest annotation. For more information on these tests for asynchronous services take a look at the restfuse site.

Restfuse is open source, licensed under the EPL v – 1.0 and is hosted at github. The 1.0 version is also in the Maven Central and online as a p2 repository (yes, it’s an OSGi bundle).  I hope this small library will help you as much as it helped me. I would appreciate feedback on how to make restfuse even better.

followme Introducing restfuse   a JUnit Extension to test REST APIs

on Aug 29th, 2011Lightweight OSGi Applications using RAP’s Widget Toolkit

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 Configurator 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!

on Aug 12th, 2011How to build a cluster with Jetty / OSGi

In this blog post I describe how to set up a cluster node with an embedded Jetty Server inside Equinox.

Basically I followed the instructions available at the Jetty Wiki page Session Clustering Using a Database [1].

There are two Jetty configuration files involved:

  • /etc/jetty.xml defining a JDBCSessionIdManager
  • /WEB-INF/jetty-web.xml defining a JDBCSessionManager

The main jetty.xml resides in the folder etc of the jetty.home.bundle which itself is a fragment of org.eclipse.jetty.osgi.boot. The jetty.osgi.boot bundle is provided by the Jetty team and is responsible for bootstrapping Jetty in an OSGi environment.

The main configuration file contains the JDBCSessionIdManager definition using a H2 database:

 <Set name="sessionIdManager">
  <New id="jdbcidmgr" class="org.eclipse.jetty.server.session.JDBCSessionIdManager">
    <Arg>
      <Ref id="Server" />
    </Arg>
    <Set name="workerName">
      <SystemProperty name="worker.name" default="primary" />
    </Set>
    <Call name="setDriverInfo">
      <Arg>org.h2.Driver</Arg>
      <Arg>jdbc:h2:tcp://localhost:9101/sessions</Arg>
    </Call>
    <Set name="scavengeInterval">60</Set>
  </New>
</Set>
<Call name="setAttribute">
  <Arg>jdbcIdMgr</Arg>
  <Arg>
    <Ref id="jdbcidmgr" />
  </Arg>
</Call>

Note: To reuse the configuration in multiple cluster nodes I use a SystemProperty tag to give every node a unique “worker.name”. The database configuration is hardwired to a local H2 database.

With additional system properties I can tell the Jetty bootstrapper where to look for the global Jetty configuration and which port the Jetty instance should bind to:

-Dworker.name=primary
-Djetty.port=18081
-Djetty.home.bundle=com.eclipsesource.cluster.jetty.home.bundle

To enable the Jetty server to load the H2 database drivers I added a dynamic import directive via the fragment org.eclipse.jetty.serverdynamic.import:

Fragment-Host: org.eclipse.jetty.server;bundle-version="7.4.2"
DynamicImport-Package: *

The web application specific configuration /WEB-INF/jetty-web.xml is located in the web bundle, com.eclipsesource.cluster.jetty.demo.webbundle. This configuration file contains the JDBCSessionManager definition.

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Get name="server">
    <Get id="jdbcIdMgr" name="sessionIdManager" />
  </Get>
  <Set name="sessionHandler">
    <New class="org.eclipse.jetty.server.session.SessionHandler">
      <Arg>
        <New class="org.eclipse.jetty.server.session.JDBCSessionManager">
          <Set name="idManager">
            <Ref id="jdbcIdMgr" />
          </Set>
        </New>
      </Arg>
    </New>
  </Set>
</Configure>

Note: “jdbcIdMgr” is a Reference to the jetty.xml from jetty.home.bundle.

If you want to try it out yourself, the code is available at GitHUB [2].

Note: The bundle com.eclipsesource.cluster.h2 contains an Eclipse launch configuration to start a local H2 database which is needed to run the example.

[1] http://wiki.eclipse.org/Jetty/Feature/Session_Clustering_Using_a_Database
[2] https://github.com/eclipsesource/com.eclipsesource.cluster

on Aug 10th, 2011How to extend the Virgo Jetty Server to support the RAP Widget Toolkit

First, a bit of news for developers following the Virgo project:  The release day for Virgo Maya is getting closer[1] with the successful RC1 release a few weeks ago.

Meantime, in this blog post I’ll describe another way of running RWT (the RAP Widget Tookit) based applications on the Virgo Jetty Server. I want to use Virgo’s RFC66 support to deploy web applications in OSGi.
The RFC66 Web Container specification creates an open standard that enables developers to deploy WAR files on OSGi. With a few modifications (see below) it is possible to deploy an RWT standalone application into an RFC66 container like Virgo.

Note: In addition to using the HttpService described here[2] with RAP 1.5 you can register RWT directly with an OSGi HTTP service. We’ll describe this in a follow-up post.

To extend Virgo you need to:

  1. Get a Virgo Jetty Server Release Candidate[3].
  2. Install our extension of Virgo as suggested here[4] into /repository/ext.

Note: You can get a patched RWT bundle here that  supports RFC66 deployment of RWT applications and the plan here. The Virgo deployment plan describes all bundles needed to support RWT applications in Virgo.

Copy the two downloaded artifacts into repository/ext:

~virgo-jetty-server> ls -1 repository/ext/*rwt*
repository/ext/org.eclipse.rap.rwt-1.5.0.plan
repository/ext/org.eclipse.rap.rwt_1.5.0.201108081102.jar

Next I added our RWT extension to the initial Virgo artifacts. This is configured in
config/org.eclipse.virgo.kernel.userregion.properties. We simply add our plan:

initialArtifacts=repository:plan/org.eclipse.virgo.kernel.userregion.springdm,\
         repository:plan/org.eclipse.virgo.jetty.web,\
         repository:plan/org.eclipse.rap.rwt

That’s all that has to be done on the Virgo side. If you start Virgo Jetty Server you should
see the extension starting properly:

[2011-08-08 12:23:45.909] system-artifacts              Installing plan 'org.eclipse.rap.rwt' version '1.5.0'.
[2011-08-08 12:23:47.626] system-artifacts              Installing bundle 'org.eclipse.rap.rwt' version '1.5.0.201108081102'.
[2011-08-08 12:23:47.663] system-artifacts              Installed bundle 'org.eclipse.rap.rwt' version '1.5.0.201108081102'.
[2011-08-08 12:23:47.665] system-artifacts              Installed plan 'org.eclipse.rap.rwt' version '1.5.0'.
[2011-08-08 12:23:47.725] system-artifacts              Starting plan 'org.eclipse.rap.rwt' version '1.5.0'.
[2011-08-08 12:23:47.729] system-artifacts              Starting bundle 'org.eclipse.rap.rwt' version '1.5.0.201108081102'.
[2011-08-08 12:23:47.734] start-signalling-2            Started bundle 'org.eclipse.rap.rwt' version '1.5.0.201108081102'.
[2011-08-08 12:23:47.737] start-signalling-2            Started plan 'org.eclipse.rap.rwt' version '1.5.0'.

Because an RWT standalone application doesn’t know about OSGi classloading, I thought that one solution might be to use buddy classloading. First, I enabled buddy classloading in org.eclipse.rap.rwt.

Bundle-SymbolicName: org.eclipse.rap.rwt
Bundle-Version: 1.5.0.qualifier
...
Eclipse-BuddyPolicy: registered

Then I registered the RWT application com.eclipsesource.sovereign.swt.layout.web as a buddy:

Bundle-SymbolicName: com.eclipsesource.sovereign.swt.dialog
...
Require-Bundle:
 org.eclipse.rap.rwt
Export-Package: com.eclipsesource.sovereign.swt.dialog
Eclipse-RegisterBuddy: org.eclipse.rap.rwt
Web-ContextPath: /rap

Note: In the MANIFEST.MF of the web bundle we specified the context path to “/rap”.

Next I setup the RAP web application. The web.xml almost looks like that of a standard RWT standalone application. For more details please go to the RAP Wiki [5]:

<context-param>
  <param-name>org.eclipse.rwt.entryPoints</param-name>
  <param-value>com.eclipsesource.sovereign.swt.dialog.SwtDialogEntryPoint</param-value>
</context-param>
<listener>
  <listener-class>org.eclipse.rwt.internal.engine.RWTServletContextListener</listener-class>
</listener>
 
<servlet>
  <servlet-name>rwtDelegate</servlet-name>
  <servlet-class>org.eclipse.rwt.internal.engine.RWTDelegate</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>rwtDelegate</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

You’ll see an additional section for the RWT resources:

<servlet>
  <servlet-name>rwtResources</servlet-name>
  <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>rwtResources</servlet-name>
  <url-pattern>/rwt-resources/*</url-pattern>
</servlet-mapping>

Now I was ready to deploy my RAP application. I simply copied the webbundle into Virgo’s pickup folder.

Note: You can get the sample RAP webbundle here.

[2011-08-08 12:25:34.421] fs-watcher                    Hot deployer processing 'CREATED' event for file 'com.eclipsesource.sovereign.swt.dialog_0.1.0.201108081127.jar'.
[2011-08-08 12:25:34.476] fs-watcher                    Installing bundle 'com.eclipsesource.sovereign.swt.dialog' version '0.1.0.201108081127'.
[2011-08-08 12:25:34.486] fs-watcher                    Installed bundle 'com.eclipsesource.sovereign.swt.dialog' version '0.1.0.201108081127'.
[2011-08-08 12:25:34.492] fs-watcher                    Starting bundle 'com.eclipsesource.sovereign.swt.dialog' version '0.1.0.201108081127'.
[2011-08-08 12:25:34.494] start-signalling-3            Started bundle 'com.eclipsesource.sovereign.swt.dialog' version '0.1.0.201108081127'.

And the application is available at localhost:8080/rap

[1] Virgo 3.0 (Maya) Release Candidate 1
[2] Running RAP on Virgo
[3] Milestone Downloads
[4] Extending Virgo with a HttpService
[5] How do I use an RWT standalone application in Tomcat

on Jul 13th, 2011Building OSGi applications that use AspectJ with Tycho / Maven 3

I just pushed a template for creating AspectJ applications with Tycho and will give you a quick tour of it here. You’ll find the template on github [1]

The template contains four infrastructure projects. One defines an OSGi command to calculate faculties and another contains an aspect to measure the duration of the calculation.

Let’s take a closer look. com.eclipsesource.weaving.demo.releng contains the Maven parent pom.xml file which defines the modules of the application:

<groupId>com.eclipsesource.sandbox.weaving.demo</groupId>
<artifactId>com.eclipsesource.sandbox.weaving.demo.parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
 
<packaging>pom</packaging>
...
<modules>
 <module>../platform</module>
 
 <module>../weaving.demo.chronometry</module>
 <module>../weaving.demo.faculty</module>
 <module>../weaving.demo.feature</module>
 
 <module>../repository</module>
</modules>

com.eclipsesource.weaving.demo.platform – contains the target definition

weaving demo target Building OSGi applications that use AspectJ with Tycho / Maven 3

com.eclipsesource.weaving.demo.feature – defines the application scope

weaving demo feature Building OSGi applications that use AspectJ with Tycho / Maven 3

com.eclipsesource.weaving.demo.repository contains the product definition. One very important VM argument, almost hidden from the debug arguments, registers the framework weaving extension:

-Dosgi.framework.extensions=org.eclipse.equinox.weaving.hook

weaving demo arguments Building OSGi applications that use AspectJ with Tycho / Maven 3

The weaving service has to be started early.

weaving demo startlevel Building OSGi applications that use AspectJ with Tycho / Maven 3

As well as the four infrastructure projects, the template contains the application code:
com.eclipsesource.weaving.demo.faculty – provides an OSGi console command to calculate faculty.

public class FacultyCommandProvider implements CommandProvider {
 
  public void _faculty(CommandInterpreter ci) {
    String argument = ci.nextArgument();
    int argumentAsInteger = Integer.valueOf(argument).intValue();
    System.out.println("Faculty of " + argumentAsInteger + " is "
          + recur(argumentAsInteger));
  }
...

com.eclipsesource.weaving.demo.chronometry – contains the Aspect to measure the faculty execution time.

public aspect CommandProviderChronometer {
  void around(CommandInterpreter ci):
        execution(void CommandProvider+._faculty(CommandInterpreter))
          &amp;&amp; args(ci) {
    long start = System.nanoTime();
    proceed(ci);
    long duration = System.nanoTime() - start;
    System.out.println("Result calculated in " + (duration / 1000) + " micro seconds");
  }
}

The following snippet from the project’s pom.xml file tells Tycho to use the aspectj compiler:

...
<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>aspectj-maven-plugin</artifactId>
      <version>1.3.1</version>
      <configuration>
        <verbose>true</verbose>
        <complianceLevel>1.5</complianceLevel>
     </configuration>
     <executions>
       <execution>
        <goals>
          <goal>compile</goal>
        </goals>
      </execution>
    </executions>
 </plugin>
 </plugins>
</build>
...

We build the application the Tycho way, from the command line with Maven 3.x:

> cd releng
> mvn package
...
[INFO] --- tycho-p2-director-plugin:0.12.0:archive-products (archive-products) @ com.eclipsesource.sandbox.weaving.demo.repository ---
[INFO] Building zip: .../weaving.demo_...-macosx.cocoa.x86_64.zip
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] com.es..weaving.demo.parent ..... SUCCESS [0.002s]
[INFO] com.es..weaving.demo.platform ... SUCCESS [0.269s]
[INFO] com.es..weaving.demo.faculty .... SUCCESS [1.995s]
[INFO] com.es..weaving.demo.chronometry  SUCCESS [0.482s]
[INFO] com.es..weaving.demo.feature .... SUCCESS [0.533s]
[INFO] com.es..weaving.demo.repository . SUCCESS [7.262s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

We can now unzip the artifact and launch the application:

> unzip weaving.demo_selfcontained-macosx.cocoa.x86_64.zip
> Eclipse.app/Contents/MacOS/eclipse

The following output shows that weaving was successful:

osgi> [org.eclipse.equinox.weaving.aspectj] info Starting AspectJ weaving service ...
...
[com.eclipsesource.weaving.demo.faculty] info register aspect com.es..CommandProviderChronometer
[org.eclipse.equinox.weaving.aspectj] info weaving bundle 'com.eclipsesource.weaving.demo.faculty'
[com.eclipsesource.weaving.demo.faculty] weaveinfo Join point 'method-execution(void com.es..FacultyCommandProvider._faculty(org.eclipse..CommandInterpreter))'
in Type 'com.es..FacultyCommandProvider' (FacultyCommandProvider.java:9)
advised by around advice from 'com.es..CommandProviderChronometer' (CommandProviderChronometer.aj:8)

Running the OSGi console command shows the measurement in action:

osgi> faculty 23
Faculty of 23 is 862453760
Result calculated in 1165 micro seconds

[1] https://github.com/eclipsesource/com.eclipsesource.tycho.aspectj.demo

on Jul 8th, 2011Single-Sourcing with declarative services

In my last blog post I introduced the idea of using OSGi services for single sourcing a RAP/RCP application. I think this approach is quite elegant, but it has one major drawback. When you use normal OSGi services in your application you will mix your application code with the OSGi Framework code everytime you reference or register a service. Not only does this look ugly, it’s also hard to test.

Luckily there is a lifesaver called Declarative Services. (For those of you who are familiar with declarative services, skip to the next paragraph.) The OSGi declarative services (ds) are specified in the OSGi compendium so they are standardized. It’s just a component framework on top of OSGi services. It gives you the ability to register and consume services in a declarative way using some xml files and simple accessors in your classes.

I’ll take the same example from in my last blog post and use it to look at ds for single sourcing.  In that blog, we single sourced a themed button widget.  We can use the same interfaces and service implementations, and the only differences will be how the services will be registered and referenced.

First, let’s take a look at the service registration. In our example we need to register the services in the rap and rcp bundles. It’s common practice to put all service declarations in a folder called OSGI-INF in the root of your project. Once you’ve created this folder you can create a “component definition” using the wizard. After this you need to fill in three things: first, the filename of your choice, second, the component name which needs to be unique in the framework and third, the component itself.

componentWizard Single Sourcing with declarative services

The component is the fully qualified classname of your implementation. In the case of service registration, it’s your service implementation. To add the service registration, press ‘Finish’ to open the component editor. We only want to register a service, so we jump to the service tab. In the bottom section you can add the service interface.

To understand what happens in the background let’s recap what we have declared. We defined a service interface, a service implementation, a component name and a filename. The component framework takes care of instantiating the service implementation and registering it as a service using the service interface. It registers the component using the component name. The filename will be automatically added to your bundle’s manifest. That’s all, the next time we start this bundle the service will be registered. Your component definition should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="com.eclipsesource.app.rap.service.provider">
   <implementation class="com.eclipsesource.app.rap.RAPSingelSourcingService"/>
   <service>
      <provide interface="com.eclipsesource.app.ISingleSourcingService"/>
   </service>
</scr:component>

Now we get to the service referencing. As you recall, we need to reference the service in our app bundle. Therefore, we need to create a component in this bundle too. In this example I decided to reference the service in the bundle’s activator and provide it with a static accessor. But you can reference it wherever you want. In this case the component is our Activator. The only difference to the service registration is in the service tab of the component editor. Instead of providing a service, we are now referencing one. You can do this by clicking ‘Add’ in the upper section of this tab.

serviceReferencing Single Sourcing with declarative services

After this you need to declare the Interface of the service you want to reference, in our case the ISingleSoucingService. The question is now, “how does this service finds its way to the Activator?” The answer is binding methods. In the reference you can specify a bind and an unbind method e.g. setService and unsetService. You need to add these methods to your activator with the service as a parameter. That’s all – we are referencing the service now. Your component should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true" name="com.eclipsesource.app.servic.consumer">
   <implementation class="com.eclipsesource.internal.app.Activator" />
   <reference bind="setSingleSourcingService" cardinality="1..1" interface="com.eclipsesource.app.ISingleSourcingService" name="ISingleSourcingService" policy="dynamic" unbind="unsetSingleSourcingService"/>
</scr:component>

The last thing we need is a little bit of glue to bring these components together. The glue is in the org.eclipse.equinox.ds bundle. This bundle contains the component framework implementation, and to make everything work together you need to add this bundle to your launch configuration. It’s not included in the RAP target components, but you can download it using the Indigo release site or the Equinox SDK.

I added a branch called “ds” to the repository on github from the last blog. This branch represents an example implementation using ds for single sourcing.

Have fun declaring services icon wink Single Sourcing with declarative services

on Jun 20th, 2011Using OSGi services to single-source an RCP and RAP Application

Probably one of RAP’s best known features is its single-sourcing capabilities. Some time ago we created a guide on Single-Sourcing RCP and RAP applications. The guide recommended a technique where a facade and fragments were used to invoke the RCP or RAP implementation during runtime. With this post I want to show you how to achieve the same the OSGi way.

For single-sourcing a RAP or RCP application, its straightforward to use the power of OSGi because it’s included in both platforms out-of-the-box. OSGi has a central concept called services which are simply POJOs and are used to allow communication between modules. And, you can register or resolve services at any time in your code.

The basic Idea behind using OSGi services for single-sourcing is as follows. We need to extract all the things that vary into separate, platform specific bundles. To use the different implementations, we have to create an interface in a “common” bundle that contains the methods we want to use. The platform specific bundles have to register an implementation of this interface as a service. In the “common” bundle we can reference the registered services and use them to get the platform specific stuff. More specifically, we register a RAP implementation in a “rap” bundle and an RCP implementation in an “rcp” bundle. The only thing we need to do then is to start the right bundles on the associated platform to get the right service.

With this solution we can extract the platform specific stuff into separate bundles and we don’t have to rely on fragments. So enough talking. Let’s look at some code. I decided to create a very simple single-sourcing interface which can be used to get the WidgetUtil.CUSTOM_VARIANT constant value. This constant exists only in RAP so, it’s a good example for showing how to handle the differences.

public interface ISingleSourcingService {
  String getCustomVariantString();
}

I have created three bundles: one that contains the application which is entitled “com.eclipsesource.app” and one for each platform. These are called “com.eclipsesource.app.rap” and “com.eclipsesource.app.rcp”. Both platform bundles implement the interface.
RAP:

  @Override
  public String getCustomVariantString() {
    return WidgetUtil.CUSTOM_VARIANT;
  }

RCP:

  @Override
  public String getCustomVariantString() {
    // There are no custom variants in RCP
    return "";
  }

And both bundles are registering the service in their Activator during the start method call.

  public void start( BundleContext bundleContext ) throws Exception {
    Activator.context = bundleContext;
    registration = context.registerService( ISingleSourcingService.class.getName(),
                                            new RAPSingelSourcingService(),
                                            null);
  }

When it comes to using the service in the common “app” bundle we can use a ServiceTracker to get the service implementation (you can also use DS).

  private ISingleSourcingService getSingleSourcingService() {
    // We use a tracker to get the service. We also can use DS to get it.
    Bundle bundle = FrameworkUtil.getBundle( getClass() );
    BundleContext context = bundle.getBundleContext();
    ServiceTracker tracker
      = new ServiceTracker( context,
                            ISingleSourcingService.class.getName(),
                            null );
    tracker.open();
    ISingleSourcingService service = tracker.getService();
    tracker.close();
    return service;
  }

The only thing we have to do now is to create two launch configurations which contain the associated platform-specific bundle.

That’s it! You can find the sources in this github repository. Have fun using OSGi services to single-source applications.

 

on Jun 13th, 2011PDE improvements, Top Eclipse Indigo Feature #8

As we count down the days until June 22nd — the day Eclipse Indigo will ship — I’ve been counting down the top 10 Indigo features, according to me.  In my previous article I talked about OSGi and how modularity plays a central role for all Eclipse projects.  With over 46 million lines of code and 62 projects, we could not ship on-time without a rock solid module system.  But modularity is not easy! Lucky for us Eclipse developers, Eclipse also ships with first class tooling for OSGi. For historical reasons this tooling is called the Plug-in Development Environment (PDE).

Number 8 on my top 10 list is the Improvements to PDE.

Target definitions allow you to manage your development-, package- and run-time dependencies and provision them from a variety of sources.  A number of improvements were made to the target management facilities.  In particular, you can now ‘update‘ your targets. This means that if you’ve defined your target in terms of p2 repositories, you can now instruct p2 to find ‘updated‘ versions of your dependencies. Also, the target facilities are now smart enough to use existing bundles that you already have on your machine.  Rid yourself of downloading the same artifacts, repeatedly.

screenshot 101 PDE improvements, Top Eclipse Indigo Feature #8

You can also specify that ‘You want source with that‘ while crafting your target definition. This option will provision the associated ‘source‘ bundles along with the binary ones making it easier to browse the source of your development time dependencies.  Special thanks goes out to Jeff McAffer for this features and Curtis Windatt for reviewing the patches.

screenshot 100 PDE improvements, Top Eclipse Indigo Feature #8

Finally, there were a number of improvements to API tooling — one of the most underrated Eclipse feature IMHO.  With Indigo you can now create consumer use reports. The standard report organizes the references by ‘producer’, that is, the bundle that produces the API.  Consumer reports organizes the references by ‘consumer’ or those bundles that ‘use’ the API.

screenshot 102 PDE improvements, Top Eclipse Indigo Feature #8

Thanks to Curtis Windatt, Ankur Sharma, Darin Wright, Chris Aniszczyk, Jacek Pospychala and Benjamin Cabe.

© EclipseSource 2008 - 2011