The first time I needed to set-up Spring in Eclipse RCP application I thought that the task can not be too complicated. Although I was right, back at the time I had many problems to make it work, mainly because I have not found any available resource that explains the process step-by-step (shame on you Google). That’s why I decided to have a short presentation on this years Eclipse Demo Camp and provide the experience gained doing the task myself. For all of you that missed this small event and have to use Spring in your RCP application this blog might be helpful.
Why Spring in RCP apps?
I am one of the core developers of the open source application performance tool inspectIT. Our application has the classic client-server architecture, where back-end is completely written using Spring. In addition, we have shared components between server and client, so called “Commons”, which are also heavily based on Spring. Thus, re-using the shared components for us would have been much easier if we also had Spring available on the client side.
In addition to this, if you are still developing on Eclipse 3.x line, with Spring you can benefit from its basic feature – dependency injection. Furthermore, we were more than happy to use AOP (Aspect Oriented Programming) feature of Spring to intercept communication with the server and handle exceptional situations. When both client and server are based on Spring, it’s very easy to alter the communication between them and even change the serialization format to something better/faster/smaller than Java serialization.
We used all these opportunities offered by Spring in our application and although most of it could be done also without Spring, having such a framework makes everything easier.
Spring Dynamic Modules
Spring DM is additional Spring project that allows a Spring based application to be deployed in OSGi container. Since a RCP application runs in Equinox, it’s all you need. This project provides 3 OSGi bundles that you will need to depend on:
The extender is the one that makes the magic possible. It’s responsible for checking if a bundle is Spring “powered” and if it is the extender will read the configuration files and create the application context. In addition, the extender will deal with any export/import of OSGi services declared by the bundle.
Step 0: Deal with the dependencies
It’s very important that before starting all needed dependencies are available. As said, the RCP application must now depend on the 3 bundles provided by Spring DM. Based on which Spring libraries you want to use, you must also include those in the list of the dependencies. However, be careful that Spring libraries you use are OSGi based. For example, the usual spring-core dependency:
<dependency org="org.springframework" name="spring-core" rev="3.1.0.RELEASE">
is not OSGi based. If you want to use spring-core library, then make sure that your dependency points to the one provided by SpringSource Enterprise Bundle Repository:
<dependency org="org.springframework" name="org.springframework.core" rev="3.1.0.RELEASE">
The mentioned repository also provides all the commonly used libraries prepared for OSGi usage. Note that Spring libraries may depend on some other bundles, thus these bundles must also be available.
Friendly advice is to only use OSGi based libraries for dependencies in your RCP application and to use Target Platform Definition (.target file) to define where all the bundles/plug-ins are located.
Step 1: Define Spring configuration
You must define the Spring configuration in XML format. If you once created such configuration file this step will not be anything new. As usual, configuration can be separated in several configuration files.
<?xml version="1.0" encoding="UTF-8"?>
<bean id="myBean" class="info.novatec.example.MyBean" />
<bean id="mySecondBean" class="info.novatec.example.MySecondBean" />
Step 2: Point Extender to the configuration files
The Spring DM Extender will consider a bundle Spring “powered” if the MANIFEST.MF of the bundle has a SpringContext entry. The entry defines where should the Extender find the configuration files. There are two options for specifying the location of the files:
- Place configuration files in the folder META-INF/spring and use:
This way all the configuration files in the META-INF/spring will be loaded.
- Place your files within your bundle and point to them:
1SpringContext: config/configFile1.xml, config/configFile2.xml
This way only explicitly defined files will be loaded.
Step 3: Define additional options for Spring context loading (optional)
The SpringContext entry in the MANIFEST.MF can define additional options for Spring context loading (default values are bold):
- create-asynchronously (true|false)
- wait-for-dependencies (true|false)
- timeout (300)
- publish-context (true|false)
The more information on what each options means can be found on the Spring Dynamic Modules Reference Guide. I find the create-asynchronously option very important, since the default value is set to true you must be sure that the asynchronous loading of the context does fit your application. For us this was not the case, thus we used:
Step 4: Force the Extender bundle to Auto-Start
The Extender bundle must be set to start before our Spring based bundle is loaded. Otherwise, the Extender will not have chance the intercept the loading of our bundle and create the Spring application context. The best is to define that org.springframeork.osgi.bundle.extender Auto-Start property is true in the .product file of your application:
Step 5: Prove it’s working
Once you did all above, the only thing left is to prove that the Extender created the Spring context. Easiest is to check the log output of the Extender bundle and prove that the Extender found specified configuration files and that all Spring beans are correctly initialized.
With Spring in place you have new possibilities like exporting any Spring bean as OSGi service. Later on same service can be retrieved from the BundleContext or imported by any other bundle. In addition, with SpringExtensionFactory you can inject any Spring bean to RCP extensions like Views or Editors.
In case you believe this blog is missing any information related to this topic I recommend these links as places for further reading:
Don’ forget to check out the inspectIT GitHub repository and see how are all these examples used the real RCP-based application.