tags:

views:

254

answers:

6

I wonder how is the best way to integrate Java modules developed as separate J(2)EE applications. Each of those modules exposes Java interfaces. The POJO entities (Hibernate) are being used along with those Java interfaces, there is no DTO objects. What would be the best way to integrate those modules i.e. one module calling the other module interface remotely?

I was thinking about: EJB3, Hessian, SOAP, JMS. there are pros and cons of each of the approaches.

Folks, what is your opinion or your experiences?

A: 

I would go for SOAP.

JMS would be more efficient but you would need to code up an message driven bean for each interface.

SOAP on the other hand comes with lots of useful toolkits that will generate your message definition (WSDL) and all the neccesary handlers (client and server) when given an EJB.

With soap you can (but dont have to) deal with certificate security and secure connections over public networks. As the default protocol is HTTP over port 80 you will have minimal pain with firewalls etc. SOAP is also great for hetrogenious clients (in your case anything that isn't J2EE) with good support for most common languages on most common platforms.

James Anderson
JMS is designed for asynchronous communication i.e. fire and forget. So if you require a response from a service call then you'll need two message channels one to receive the message and the other to send the reply back to the sender.
pjp
The issue that I see with SOAP is that using this technique requires definition of XML schema that I can then use to bind XML to object (JAXB). As I stated in my original post, the goal is to eliminate DTOs and use model entities (Hibernate/JPA) when possible. The problem with DTOs is that the conversion layer is required between DTOs and entities.
pregzt
@pjp: Not exactly. You can use the pattern that involves private queues (for a session) to receive the response. Basically, the client creates temporary queue, sets 'ReplyTo' property for request message and fires the message to public request queue. The responder receives the request message, kicks off the logic, creates response message and send it to the temporary queue as specified in 'ReplyTo' of the request message.
pregzt
+1  A: 

If you need network communication between Java-only applications, Java RMI is the way to go. It has the best integration, most transparency and the least overhead.

If, however, some of your clients aren't Java-based, you should probably consider other options (Java RMI actually have an IIOP-dialect, which allows it to interact with CORBA, however - I wouldn't recommend doing this, unless it's for some legacy-code integration). Depending on your needs, webservices are probably your friend. If you are conserned with the networkload, you could go webservices over Hessian.

cwap
+1 RMI is the easy and straightforward solution :-)
ATorras
+1  A: 

You literally mean remotely? As in running in a different environment with therefore different availability characteristics? With network overheads?

Assuming "yes" my first step would be to take a service approach, set aside the invocation technology for a moment. Just consider the design and meaning of your services. You know they are comparativley expensive to invoke, hence small busy interfaces tend to be a bad thing. You know that the service system might fail between invocations, so you may favour stateless services. You may need to retry requests after failure, so you may favour idempotent service designs.

Then consider availability relationships. Can your client work without the remote system. In some cases you simply can't progress if the remote system isn't available (eg. can't enable the employee if you can't get to the HR system) in other cases you can adopt a "fire-and-tell-me-later" philosophy; queue up the requests and process responses later.

Where there is an availability depdency, then simply exposing a synchronous interface seems to fit. You can do that with SLSB EJBs, if everything is JEE, that works. I tend to generalise expecting that if my services are useful then non JEE clients may want them too. So SOAP (or REST) tends to be useful. These days adding a web service interface to your SLSB is pretty trivial.

But my pet theory is that any sufficiently large IT system ends up needing aynch communications: you need to decouple the availability contraints. So I would tend to look for a JMS-style relationship. An MDB facade in front of your services, or SOAP/JMS is not too hard to do. Such an approach tends to highlight the failure-case design issues that were probably lurking anyway, JMS tends to make you think: "suppose I don't get an answer? suppose my answer comes late?"

djna
+3  A: 

The standard approach would be to use plain RMI between the various service components but this brings issues of sharing your Java interfaces and versioning changes to your domain model especially if you have lots of components using the same classes.

Are you really running each service in a separate VM? If these EJBs are always talking to each other then you're best off putting them into the same VM and avoiding any remote procedure calls as these services can use their LocalInterfaces.

The other thing that may bite you is using Hibernate POJOs. You may think that these are simple POJOs but behind the scenes Hibernate has been busy with CGLib trying to do things like allow lazy initialization. If these beans are serialzed and passed over remote boundaries then you may end up with odd Hibernate Exception getting thown. Personally I'd prefer to create simple DTOs or write the POJOs out as XML to pass between components. My colleagues would go one step further and write custom wire protocols for transferring the data for performance reasons.

Recently I have been using the MULE ESB to integrate various service components. It's quite nice as you can have a mix of RMI, sockets, web services etc without having to write most of the boiler plate code.

http://www.mulesource.org/display/COMMUNITY/Home

pjp
+1 I like the ESB approach
ATorras
I'd forgotten where my preference to VOs/DTOs had come from - it was nasty Hibernate lazy-loading issue where their collection implementations get serialized along with the Hibernate session that is effectively meaningless in the calling code - watch out for that one.
Nick Holt
A quick way to serialize out the POJOs would be to use XStream. It's not as nice as using your own XSD but is good enough for sending data around to systems that you control. http://xstream.codehaus.org/
pjp
Nick, this is something that bothers me a lot! I wasn't big fan of the VOs/DTOs, but I've started to consider to lean towards these a little bit more :)
pregzt
@Pregzt - I think there's subtle differents with the objects you use for you wire protocol (the VOs/DTOs) and those you use in your application (the POJOs). The most obvious one I can think of is VOs/DTOs having getters and setters for all attributes while I like POJOs to only have setter for genuinely readwrite attributes as it helps communicate to other developers what can and can't be set.
Nick Holt
+2  A: 

Why would you go with anything other than the simplest thing that works?

In your case that sounds like EJB3 or maybe JMS, depending on whether the communication needs to be synchronous or asynchronous.

EJB3 is by far these easiest being built on top of RMI with the container providing all the additional features you might need - security, transactions, etc. Presumably your POJOs are in a shared jar and therefore can simply be passed between your EJBs, although I tend towards passing value objects myself. The other benefit of EJB is, when done right, that it's the most performant (that's just my opinion btw ;-).

JMS is a little more involved, but not much and a system based on asynchronous communication affords certain niceties in terms of parallelizing tasks, etc.

The performance overhead of web-services, the inevitable extra config and additional points of failure make them, IMHO, not worth the hassle unless you've a requirement that mandates their use - I'm thinking interop with non-Java clients or providing data to external parties here.

Nick Holt
@pjp's answer above reminded me why I prefer DTOs - for lazy loading to work the Hibernate session gets in everywhere, most noticeable in their collection implementations. When these objects are serialized the Hibernate session is too and it's meanless client-side, blowing-up when invoked. There is a Hibernate.initialize(Object) method that can be called to work round this but my preference is still DTOs
Nick Holt
+5  A: 

Having dabbled with a few of the remoting technologies and found them universally unfun I would now use Spring remoting as an abstraction from the implementation. It allows you to concentrate on writing your functionality and let Spring handle the remote part with some config. you have the choice of several implementations (RMI, Spring's HTTP invoker, Hessian, Burlap and JMS). The abstraction means you can pick one implementation and simply swap it if your needs change. See the SpringSource docs for more information.

Rich Seller
We use this in a system with HTTP from client to server (required for security reasons), and using both JMS and EJB for service to service calls.
Robin