views:

1916

answers:

9

We currently have a web application loading a Spring application context which instantiates a stack of business objects, DAO objects and Hibernate. We would like to share this stack with another web application, to avoid having multiple instances of the same objects.

We have looked into several approaches; exposing the objects using JMX or JNDI, or using EJB3.

The different approaches all have their issues, and we are looking for a lightweight method.

Any suggestions on how to solve this?

Edit: I have received comments requesting me to elaborate a bit, so here goes:

The main problem we want to solve is that we want to have only one instance of Hibernate. This is due to problems with invalidation of Hibernate's 2nd level cache when running several client applications working with the same datasource. Also, the business/DAO/Hibernate stack is growing rather large, so not duplicating it just makes more sense.

First, we tried to look at how the business layer alone could be exposed to other web apps, and Spring offers JMX wrapping at the price of a tiny amount of XML. However, we were unable to bind the JMX entities to the JNDI tree, so we couldn't lookup the objects from the web apps.

Then we tried binding the business layer directly to JNDI. Although Spring didn't offer any method for this, using JNDITemplate to bind them was also trivial. But this led to several new problems: 1) Security manager denies access to RMI classloader, so the client failed once we tried to invoke methods on the JNDI resource. 2) Once the security issues were resolved, JBoss threw IllegalArgumentException: object is not an instance of declaring class. A bit of reading reveals that we need stub implementations for the JNDI resources, but this seems like a lot of hassle (perhaps Spring can help us?)

We haven't looked too much into EJB yet, but after the first two tries I'm wondering if what we're trying to achieve is at all possible.

To sum up what we're trying to achieve: One JBoss instance, several web apps utilizing one stack of business objects on top of DAO layer and Hibernate.

Best regards,

Nils

A: 

Take a look at JBossCache. It allows you to easily share/replicate maps of data between mulitple JVM instances (same box or different). It is easy to use and has lots of wire level protocol options (TCP, UDP Multicast, etc.).

Todd
+4  A: 

Are the web applications deployed on the same server?

I can't speak for Spring, but it is straightforward to move your business logic in to the EJB tier using Session Beans.

The application organization is straight forward. The Logic goes in to Session Beans, and these Session Beans are bundled within a single jar as an JEE artifact with a ejb-jar.xml file (in EJB3, this will likely be practically empty).

Then bundle you Entity classes in to a seperate jar file.

Next, you will build each web app in to their own WAR file.

Finally, all of the jars and the wars are bundled in to a JEE EAR, with the associated application.xml file (again, this will likely be quite minimal, simply enumerating the jars in the EAR).

This EAR is deployed wholesale to the app server.

Each WAR is effectively independent -- their own sessions, there own context paths, etc. But they share the common EJB back end, so you have only a single 2nd level cache.

You also use local references and calling semantic to talk to the EJBs since they're in the same server. No need for remote calls here.

I think this solves quite well the issue you're having, and its is quite straightforward in JEE 5 with EJB 3.

Also, you can still use Spring for much of your work, as I understand, but I'm not a Spring person so I can not speak to the details.

Will Hartung
Yes, everything is deployed to the same server. This looks quite interesting, I'll give EJB a shot today. My point about Spring is that it offers to wrap beans for e.g. JMX without any code, but apparently not for EJB. Anyway, I look at the EJB approach today.
Nils-Petter Nilsen
+3  A: 

Terracotta might be a good fit here (disclosure: I am a developer for Terracotta). Terracotta transparently clusters Java objects at the JVM level, and integrates with both Spring and Hibernate. It is free and open source.

As you said, the problem of more than one client web app using an L2 cache is keeping those caches in synch. With Terracotta you can cluster a single Hibernate L2 cache. Each client node works with it's copy of that clustered cache, and Terracotta keeps it in synch. This link explains more.

As for your business objects, you can use Terracotta's Spring integration to cluster your beans - each web app can share clustered bean instances, and Terracotta keeps the clustered state in synch transparently.

Scott Bale
A: 

I'm not really sure what you are trying to solve; at the end of the day each jvm will either have replicated instances of the objects, or stubs representing objects existing on another (logical) server.

You could, setup a third 'business logic' server that has a remote api which your two web apps could call. The typical solution is to use EJB, but I think spring has remoting options built into its stack.

The other option is to use some form of shared cache architecture... which will synchronize object changes between the servers, but you still have two sets of instances.

Not so if you use Terracotta
Taylor Gautier
+2  A: 

Actually, if you want a lightweight solution and don't need transactions or clustering just use Spring support for RMI. It allows to expose Spring beans remotely using simple annotations in the latest versions. See http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.

Jevgeni Kabanov
I have used this approach to access shared Spring beans from a webapp. It works though I still feel there is probably a better/cleaner solution.
Mark
If you don't like RMI, Spring offers a few other remoting options - Hessian, Burlap, and HttpInvoker (Spring's custom remoting solution - Java serialization over HTTP). Of course there are always web services as well.
matt b
+1  A: 

Thank you for your answers so far. We're still not quite there, but we have tried a few things now and see things more clearly. Here's a short update:

The solution which appears to be the most viable is EJB. However, this will require some amount of changes in our code, so we're not going to fully implement that solution right now. I'm almost surprised that we haven't been able to find some Spring feature to help us out here.

We have also tried the JNDI route, which ends with the need for stubs for all shared interfaces. This feels like a lot of hassle, considering that everything is on the same server anyway.

Yesterday, we had a small break through with JMX. Although JMX is definately not meant for this kind of use, we have proven that it can be done - with no code changes and a minimal amount of XML (a big Thank You to Spring for MBeanExporter and MBeanProxyFactoryBean). The major drawbacks to this method are performance and the fact that our domain classes must be shared through JBoss' server/lib folder. I.e., we have to remove some dependencies from our WARs and move them to server/lib, else we get ClassCastException when the business layer returns objects from our own domain model. I fully understand why this happens, but it is not ideal for what we're trying to achieve.

I thought it was time for a little update, because what appears to be the best solution will take some time to implement. I'll post our findings here once we've done that job.

Nils-Petter Nilsen
It's been suggested several times on this thread by myself and others, but have you looked at Terracotta? Unlike all the other solutions presented thus far, it is designed explicitly for state sharing which is what you asked for.
Taylor Gautier
+2  A: 

You should take a look at the Terracotta Reference Web Application - Examinator. It has most of the components you are looking for - it's got Hibernate, JPA, and Spring with a MySQL backend.

It's been pre-tuned to scale up to 16 nodes, 20k concurrent users.

Check it out here: http://reference.terracotta.org/examinator

Taylor Gautier
+3  A: 

What about spring parentContext? Check out this article:

http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html

Dan
+1  A: 

Spring does have an integration point that might be of interest to you: EJB 3 injection nterceptor. This enables you to access spring beans from EJBs.

Kees de Kooter