jump to navigation

springOSGi May 20, 2007

Posted by Bernd in equinox, spring, springOSGi.
trackback

A few weeks ago, the springframework released the 2nd milestone of the spring-OSGi bridge.

In my free time over the last two weeks I ported Jürgen Höllers jPetStore example to springOsgi based on M2 (more or less, I still had some issues with broken manifests), Eclipse Equinox (with a Jetty running inside) iBATIS and HSQLDB in the backend and Spring WEB-MVC at the frontend.

Project setup

First of all, I needed to find a way to get springOSGi into Eclipse. The thrilling thing there has been to find a possibility to debug the spring and the springOSGi bridge… If you just copy the bundles into your target, Eclipse is not able to find the source code. Finally I got the solution. For me it worked best use the “Import Plug-ins and Fragments” Wizard to import the bundles as binary projects into my workspace. Now I was able to attach the source code. However, I don’t really like the way springOSGi is distributed. If you have a look to the download, you’ll find a folder lib which contains all the libraries, including spring itself, coming with springOSGi. But you don’t find the jars in there, but a whole bunch of folders: one for each library. Inside such a folder again you don’t find the jars, but another folder. Inside this folder you finally get the jar. This structure seems to come from the maven build.

The easiest thing you can do if you are using the same setup as me is to just search for all jars in the download and copy them to one location. Then use this location for your import.
Alin Dreghiciu has reported another solution just some days ago. This also seams to work very well.

Analyzing the example

When I started, I’d just wanted to see how well the current bridge already was and what I had to do to refactor a running spring application. As an example I have chosen the jPetStore example which comes with the official spring distribution. jPetStore is a simple web-App with a database in the backend. Additionally it uses spring-remoting for the communication with another client.

For me, this example has been mainly a technical prototype. So I decided to create a bundle for each of the technical layers (database, domain-logic and web) and one for the business objects.

Implementation

Dataaccess Layer

I started with the database layer. The example uses iBATIS and apache.commons.dbcp. As I wanted to change as little as possible at the example I decided to use the same libraries. This was a pretty easy task. The stumbling blocks here have been the broken manifest of commons.collections which came with the official distribution (org.springframework.osgi.commons-collections.osgi has a broken manifest) and the fact that BasicDatasource from DBCP does not respect the context classloader.
As iBATIS has not been in the set of libs that came with the download I had to create a bundle for that on my own. Using the PDE-Project-Creation-Wizard this is really easy. The only thing I added to the generated Manifest was the Eclipse-BuddyPolicy (Eclipse-BuddyPolicy: registered). The only registering bundle is bundle containing the domain-objects. This has also been the only point where I used non-osgi standard mechanisms from equinox.

When running the example the first time, I had to make sure, that the bundle with the symbolic name org.springframework.osgi.spring-osgi-extender has a lower startlevel than my application bundles. Otherwise the spring application contexts of my bundles might not be loaded.

Middle-tier

The next layer has been the middle tier. Nothing interesting about the business logic, but this layer also includes some http-based service exporters. Milestone 2 has no support for that. So I had to implement some utilities to make the spring-web-support working in OSGi.
The main issue here has been the locating and loading of resources. All of that has been factored out to a utility bundle to keep it reusable.
Another problem has been the process of registering servlets and resources. I decided to use the OSGi HTTP service implementation by Equinox which uses Jetty as servletcontainer. (Some useful utilities are implemented in the org.eclipse.equinox.http.helper bundle which can be checked out from the eclipse repository (Server: :pserver:anonymous@dev.eclipse.org:/cvsroot/eclipse Module: /equinox-incubator/org.eclipse.equinox.http.helper))

In order to get this service I used a ServiceTracker. As in springOSGi each bundle has its own ApplicationContext, the ApplicationContext of the bundle is also needed to create the context for the web application.In a first version I implemented the servlet-registration in the bundles BundleActivator, but there the only possibility to get the ApplicationContext is to import the ApplicationContext as an OSGi service. According to the spec, this is not the way to go (The ApplicationContext you get is from a specific bundle, but you don’t know from which version of the bundle). Another problem with this implementation was the timing: the ApplicationContext is exported as a service after the start() method of the BundleActivator was executed. Hence it is not possible to register the http stuff in the start method. It has to be done asynchronously. So this was a hack.

In the second version I have created a little utility which implements ApplicationContextAware and BundleContextAware. This utility has to be added to the application context of the bundle. From that utility you can get a callback after the ApplicationContext and the BundleContext/HttpService has been set. Additionally I had to add several 3rd party libs and exchanged some of the libs which have been included in M2 because some packages have not been included in the libs. (Missing packages in several bundles)

Last but not least, Jürgen used some springAOP for transactions. After creating a bundle for aspectj which contains the aspectjweaver.jar and adding dependencies to the respective packages this also worked out of the box :-)

Web-tier

After all the registration problems have been solved, I continued with the web layer. Here, the exciting question has been what has to be done to support spring webMVC and JSPs. Equinox comes with a JSPServlet which uses jasper internally to render the JSPs. So this was a really easy job. While adding the dependencies, I noticed that spring comes with a jstl bundle, but does not include the apache commons standard taglibs. This causes a cyclic dependency. As standard taglibs need jstl and vice versa. So I created my own bundle for that and opened this bug org.springframework.osgi.jstl.osgi should include standard.jar.
Now I had to fight a bit with the internals of jasper and see how it resolves (or better tries to resolve) the TagLib definitions. After some debugging I finally noticed that the only possibility for me to place tld-files was a folder called WEB-INF relative to the web-context-path you had to specify when registering the equinox JSP-Servlet ( I used

JspServlet servlet = new JspServlet(context.getBundle(), "/web");

so the Taglib definitions had to be in a folder /web/WEB-INF relative to the bundles root.)

Conclusion

After sailing around this last rock Jürgens jPetStore finally worked :-) It has not always been an easy job, but given the fact that it is a pre-1.0-release it was pretty straight-forward after the initial installation problems. Most of the problems I had have just been broken manifests and missing dependencies in the libraries coming with the springOSGi bridge.

If you are interested, I have uploaded my workspace to http://www.kolbware.de/springOsgi/jPetStoreOSGi.zip. It contains all the necessary bundles including equinox as OSGi platform. The de.kolbware.jpetstore.launcher project contains launchconfigurations for HSQLBD and the web application itself.
I’d be happy about feedback.

Have fun

Bernd

About these ads

Comments»

1. Matthias - May 21, 2007

Awesome.
For the record: Bernd published the first SpringOSGi-App!

2. Ingo Meyer - May 21, 2007

Very helpfull.
Maybe a description how to run from eclipse is missing:
How to start and setup the database and the url of the shop.

3. Bernd - May 21, 2007

Hi Ingo!
Yes, of course you’re right. Sorry!

So here we go:

I used Eclipse 3.3M7. To import the projects into your workspace, go to the package explorer and hit the right mouse button. Choose Import… and then General -> Existing projects into workspace. Next, choose the jPetStoreOSGi.zip and import all the containing projects. You have to have Java 1.5 (I used 1.6) installed and set as default JRE. Despite that you need a 1.4 JRE to compile the patched commons.dbcp. Just add this 1.4 version as an additional jre to eclipse (Window -> Preferences… -> Java -> Installed JREs)

After doing that none of the bundle projects should contain errors. I just noticed, that jasper and jetty 5 still have errors, but this does not matter as I just used their sources to debug. I added them to the zip by accident.

The zip contains a project de.kolbware.jpetstore.launcher. It contains eclipse launch-configs for the database server and the web application. Using this launch configs, it should work out of the box. To run these launch configs, open the run dialog. There should be a little expand-icon in front of the Java Application entry and the OSGi Framework entry in tree on the left side. The database can be started using the HSQLDB config, the launch config for the web-server is called “jpetstore with web” The web-server will be started at port 8081 (can be configured on the arguments tab) and the URL to the app is http://localhost:8081/index.html (the /index.html is important)

HTH

Bernd

4. Jeff Constantin - May 24, 2007

Bernd — nice work here. I can’t even guess how much work this was to pull it all together.

Any chance you have this working on JBossAS 4.0.5.AS?

5. Bernd - May 24, 2007

Jeff, so using the equinox servlet bridge, it should be an easy job I guess :-) You just have to change the few places where the servlets have been registered.

6. Solomon - May 31, 2007

Hi Bernd,

JPetStore over OSGi was like a light at the end of the tunnel for me. I do have a couple of questions.

1) I can’t seem to connect to HSQLDB: “user SA not found”
Any thoughts on this problem?

2) It seems like you had to write a lot of glue code yourself in order to get a webapp running. Do you think that Spring-OSGi has progressed enough to start using it on a full-fledged application?

7. Bernd - May 31, 2007

Hi Solomon,

Your database problem is a bit strange… Have you started the database using the Eclipse Launch Configuration included? If so, the database should be set up properly.
In the Console View you should see something like the following lines:

[Server@1d58aae]: [Thread[main,5,main]]: checkRunning(false) entered
[Server@1d58aae]: [Thread[main,5,main]]: checkRunning(false) exited
[Server@1d58aae]: Startup sequence initiated from main() method
[Server@1d58aae]: Loaded properties from [C:\projects\serversidespring\de.kolbware.jpetstore.launcher\hsqldb\server.properties]
[Server@1d58aae]: Initiating startup sequence…
[Server@1d58aae]: Server socket opened successfully in 109 ms.
[Server@1d58aae]: Database [index=0, id=0, db=file:jpetstore, alias=] opened sucessfully in 829 ms.
[Server@1d58aae]: Startup sequence completed in 938 ms.
[Server@1d58aae]: 2007-05-31 18:26:23.875 HSQLDB server 1.8.0 is online
[Server@1d58aae]: To close normally, connect and execute SHUTDOWN SQL
[Server@1d58aae]: From command line, use [Ctrl]+[C] to abort abruptly

Can you see that? Please come back to me I you still have problems with the database!

Regarding your second point:
Yes, I had to write some glue-code, but I think the amount of work there was acceptable. I personally think that the foundation of springOSGi is really stable and don’t expect to much problems on that side. So from this perspective I think springOSGi is already ready to use. However you might run into some problems with 3rd party libs if they don’t get around with the dynamics and the classloading provided by OSGi. E.g in Hibernate it is not possible at the moment to unsubscribe registered resources… You you have to check carefully which libs to use in which context.

8. Solomon - May 31, 2007

Thanks Bernd.

I did start HSQLDB the way you described. I ended up creating a new database (jpetStore2) and cutting & pasting the sql into the Manager…

Your Hibernate insights are pretty interesting… There does seem to be a lot of discussion about Hibernate & OSGi.

I guess for now, I’d be shy to use Spring-OSGi in production, but with the work of trailblazers like you, there’s enough information out there for a newbie to come onboard pretty quickly…

Thanks again for your work. Your fully fleshed out example helped me understand a lot about the inner workings of Spring-OSGi.

9. Michael Sueess - June 1, 2007

i have the same database problem

when clicking on a category the following error occurs:

Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (User not found: SA)

ny ideas?

10. Bernd - June 1, 2007

Hmm…. The database problem is really strange! There is another launch configuration called HSQLDB Manager. Can you please start HSQLDB and then the Manager. Connect to jdbc:hsqldb:hsql://localhost:9002/ and see if you can log in. AFAIK, sa is the default admin user for HSQLDB.
BTW: Is it maybe a platform problem??? Are you Michael and Solomon using Windows or another OS?

11. Michael Sueess - June 4, 2007

I am using windows with eclipse 3.3 RC3;
also HSQLDB Manager is not able to find the (default) user SA: “java.sql.SQLException: User not found: SA”
also quantumdb, an eclipse plugin for db development cannot find the suer SA

12. Peter Joosten - June 7, 2007

The following fixed the “User not found: SA” problem for me:
1. Launch the HSQLDB Manager.
2. Connect using the HSQL DB Engine Standalone,
url = jdbc:hsqldb:file:jpetstore.
3. Open script jpetstore-hsqldb-schema.sql and execute
4. Open script jpetstore-hsqldb-dataload.sql and execute
5. Refresh the hsqldb folder in the eclipse “launcher” project.
The file jpetstore.script should now contains the SQL statements to create the database, and also CREATE USER SA PASSWORD “”.
Now:
1. launch HSQLDB
2. launch jpetstore with web.

Bernd, thanks for this nice spring-OSGi app.

Greetings
Peter Joosten.

13. Bernd - June 9, 2007

Peter,
Thanks a lot!!!
Hopefully this app is now working for everybody.

14. chanwook - March 17, 2008

Hi, Bernd.
Thanks to Really Helpfull article!
I try it now, and ver useful!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: