Recently I have been trying to learn a mix of Spring Restful web-services and IBATIS, but in this journey I started to get a little frustrated with them both. I admit this is probably due to my lack of knowledge with both of those frameworks, but recently I discovered that I purchased an O'Reilly book over 12 months ago on EJB 3 and thought "I wonder if that's any better". Certainly if you read the hype on Spring you will be convinced that EJB is heavy weight, complicated and typically the wrong option.
I've only read about four chapters in the book, but so far I must admit it's cleaner and simpler than I expected. You could argue that Spring has many features that would be advantageous, such as dependency injection, but in my opinion the level of dependency injection provided within EJB 3 is probably sufficient for my needs. Spring seems to be growing almost daily and I started to feel like I was drowning rather than at least treading water - but I haven't given up. I successfully managed to use the new Spring annotations to expose Restful web-services, plus started to integrate with IBATIS, but I was getting increasingly concerned about parts of my code getting more and more coupled to Spring.
This past week I have been looking at restructuring my code, to enable me to support different frameworks (Spring and EJB for exposing business methods over the network from a client and various persistence technologies in the server).
Below is a diagram that sums up where I am at the moment.
I'll try to explain in words how to interpret my class diagram - but bear in mind, some of the relationships are hiding what really goes on behind the scenes, but should give you a general idea.
First, if you're new to EJB 3 like me, it's worth pointing out to you that you can pretty much develop your business logic using plain old Java objects (POJOs) and then add Java 5 annotations to 'decorate' them with EJB 3 features, for example, I have annotated my UserStatelessSessionBean with two EJB 3 annotations, EndPoint and Stateless. Those annotations will indicate that a SOAP based web-service should be used to access the service and that the bean is not expected to hold state between requests, the latter enables many requests to share the same object and increase scalability.
The MyStatefulSessionBean used three annotations Local indicates that certain methods can be invoked from within the same JVM without the overhead of remote method calls, dramatically increasing performance - but this does not help you if you want to access the methods from a client application. In this scenario I have used the Remote annotation to indicate that the methods will be accessible via JAX-RPC style web service requests. The Stateful annotation indicates that this bean is expected to hold state across invocations and therefore it can't be shared between sessions.
From my understanding, Stateful session beans are closely linked to fine-grained services, i.e. you might invoke the service with 20 messages/methods to do one job. Whereas Stateless session beans are closely linked to course-grained services, i.e. you might invoke only one method to do one job (use-case). I have yet to throw myself into this to fully appreciate one model over the other, but my suspicion is that scaleability is best achieved by being as stateless as possible. My rational for this is to consider some large application like facebook, if you have a simple course-grained service that says something like postMessage(myUserId, targetUserId, theMessage), then the message has everything it needs to service the request and could therefore be sent to any server in a cluster, enabling load balancing and all those wonderful things to work best. If I used a stateful session bean, either the state gets replicated across the cluster which must be slow, or you are restricted to talking to the originating server to complete your session.
My aim in this class diagram is to show flexibility and therefore re-use. Firstly I have a GUI that talks via an interface to 'do things', then I have an implementation of that interface that uses EJB3 and another that uses Spring. This means that if I find one to be more reliable, faster, better suited for intranet/public internet access, I can easily swap the client to server communications very quickly, without affecting any GUI code!
The same can be said on the server, The EJB session beans and Spring web-services are controllers that I have made as dumb as possible. The controllers simply delegate their work to a Manager class that does all the business logic. This means I can add say a CORBA controller, or perhaps implement the Google protocol buffers and re-use all the manager code as-is. Obviously if I add some features in the server, I might want to add the option in the GUI to use that new service too.
Okay, so far this all sounds dandy, but is it really likely that I want to swap between Spring or EJB or Google protocol buffers? Well, perhaps not, but the option would be nice wouldn't it?! There is another good reason for doing this though, perhaps you can expose these APIs to enable other developers to add value to your application, the more API's you expose, the more chance you have of increasing developers to your API.
The last part of my class diagram is to show that I've done the same thing with the Data Access Object, I can therefore implement the DAO using EJB3 JPA or IBATIS, Hibernate or pure JDBC.
The Domain objects can remain POJOs in most (if not all) cases, therefore my intention is to re-use the domain objects in the client tier and server tier.
I guess at some point I will have a sample application to prove my thoughts, but in the meantime, if anyone has any comments then I would be very happy to learn from you!