Recently came across a problem wherein, one application say (A) needs to communicate with another application say(B). But there are many versions of application B (say B1, B2 and B3). Each version has same package, class and API names for their respective implementations and are deployed in different regions. Where as A is a global application with one version and needs to communicate with respective version of B based on region of a request.
- Posted by: Nikhil Sharma
- Posted on: July 16 2004 04:22 EDT
Both A and B are pure J2EE applications having their own set of EJBs in business and servlets/jsps in presentation.
There definitely is an issue that why there are various versions with same name of classes and differing in composition for application B. But that more or less happens in the projects either due to vague requirements or incomplete design or last minute changes.
The problem at hand is to allow application A to seamlessly communicate with B1, B2 and B3.
To enable this communication there is following conventional way used by many projects -
-Change the package names to include the version numbers of the application. But this seems like a very crude and not so maintainable way of achieving the objective. And is also tedious and error-prone at this stage.
Another approach is to build an Adapter class which will create class-loaders for different versions of the application B and will allow seamless communication. But creation of class-loader inside EJB Container is generally not recommended.
So I was wondering, can we not develop this Adapter as a simple SLSB and wrap it up in 3 different ejb jars with respective version's value-object classes from B1, B2 and B3. This way the different class-loaders will be provided by the container inherently and A can communicate seamlessly with all three versions of B with ambiguity of classes getting resolved by container class-loader heirarchy.
Only issue is that the application A will need to deploy these Adapter beans in its environment.
Wanted to check is there any better approach available which is extensible for future versions and less tedious to implement. Or else, any possible flaws in the EJB based approach.
Why don't you utilize the class versioning as supported by Java's serialization mechanism?
The default algorithm supports the following changes to the class definition:
* adding a field
* adding classes
* removing classes
* adding writeObject/readObject methods
* removing writeObject/readObject methods
* adding java.io.Serializable
* changing access modifiers to a field
* changing a field from static to nonstatic or transient to nontransient.
provides partial support for the following changes:
* deleting fields
* changing nonstatic to static or nontransient to transient
* renaming a field
But does not support the following changes:
* moving classes up or down the hierarchy
* changing declared type of a primitive field
* changing readObject/writeObject incompatibly
* changing a class from Serializable to Externalizable
* removing either Serializable or Externalizable
* adding writeReplace or readResolve methods incompatibly
To benefit from this support, all you have to do is to ensure that the serialVersionUID is specified in all your data transfer objects and that you apply compatible changes only.
Incompatible changes will require you to redistribute the ejb-client jar. By assigning a different JNDI names to your incompatible versions of B, your clients will be able to select the appropriate version.
Hope this helps,
Nikhil,Why don't you utilize the class versioning as supported by Java's serialization mechanism?This is also one of the options, but if taken care of from the begining. At current stage it would involve code changes in many classes.
thanks for the pointers.
#1: I have seen this method used in full scale by one very good software vendor delivering one of the big billing systems available on the market. (I don't vant to tell you the name of the product, and you cannot access their code or documentation without buying it anyway.) It seems to work fine, but - as you say - this is not something you should introduce late in the project.
#2: Creating classloaders in the EJB container looks like a bad idea. See section 25.1.2 in the EJB 2.1 specification. "The enterprise bean must not attempt to create a class loader [...]"
#3: To me, this seems to be a good solution. I suppose there will be some sort of adapter or factory on top of the different versions (to provide a common point of access). And you must have some sort of database (a table or properties file) saying what version different B's use.