When you consider thisproblem you start to think how complex it can be.
- Posted by: Thierry Janaudy
- Posted on: May 16 2001 13:01 EDT
In the situation where EJB A has a relationship with EJB B, you cannot upgrade B without upgrading A, otherwise you will face some class cast exceptions.
Even worse if you are in a cluster as the lookup may direct you to another JVM on a different physical box.
I thought about the following:
- Create a custom JNDI lookup that will return a reference to the remote object (EJBHome or EJBObject)
- Always use the reflection API to invoke methods on the EJBs (This will avoid the class cast problem)
- Return the old version if the caller has a version number < to the bean being looked up
By doing this you can upgrade the beans in a cluster using a different JNDI name that contains the version number like MailBean-v1d0 MailBean-v2d0 …
If you have UserBean-v2d0 that uses MailBean-v2d0 you can add MailBean-v3d0 and the User bean uses the custom JNDI lookup that will return MailBean-v2d0 because User bean's version 2 < Mail Bean's version 3, until User is upgraded to version 3.
It should work in a cluster because the version taken is the one from the current instance.
Of course the User bean does not have any import org.jyperion.mail.*; but instead a import javax.ejb.EJBHome and javax.ejb.EJBObject. Those instances are returned by the JNDI lookup (The home interface extends EJBHome and the remote interface EJBObject), then within the user bean, we use reflection in order to dynamically call the method on the Mail bean.
I really would like to hear from you.
- EJB versioning in a cluster environment by Krishnan Subramanian on May 17 2001 12:03 EDT
- EJB versioning in a cluster environment by Thierry Janaudy on May 18 2001 04:59 EDT
- EJB versioning in a cluster environment by Guglielmo Lichtner on September 06 2001 13:14 EDT
A normal JNDI lookup (as you mention) could return a reference to an EJB in another container - in other words - there is no guarantee that the reference returned by a JNDI lookup will refer to an object (or EJB) in the same container.
*But* if you define EJB links or references (java:comp/env/...) between beans, then a look up *will* return a reference to a bean in the same container/process (or JAR/EAR file).
Besides this, a lookup via EJB links/references is potentially less expensive than a normal JNDI lookup because the container/ejb server can enforce a [co]locality constraint.
And finally if you do use EJB links/references to establish links between beans, you are ensuring that beans that 'use' each other do so in the same process. If you use a normal JNDI, and if the returned reference is an object on another server, then you incurring the costs of RPCs, transaction contexts being propagated across processes etc.
Bottom line: use EJB links/references for co-operting beans.
(Hope that answers your question on class versioning as well)
Thank you for your answer.
In other words, what you are suggesting is that if bean A has a relation with bean B, I use EJB links from A to lookup for B for example. (What I am currently doing).
The problem I think is that If I have the following situation:
A 1<->1 C and B 1<->1 C, using references (java:comp/env) with A.jar, B.jar, C.jar.
If I need to upgrade C, I will have to recompile and redeploy A and B as well.
I understand the benefits of having strong typing when importing the home and remote interfaces of C in A and B,
but for flexibility the use of Reflection would allow
me to upgrade C (using hot deployment) without recompiling
and upgrading A and B.
If the cost of using Reflection is linear and not exponential when the number of calls increase, it wouldn't
be a problem, would it be?
You cannot have EJB links between EJBs in different jars.(Actually you can if you package your JARs in an EAR).
The question is not whether to reflect or not to reflect ;) but of putting co-operating beans in the same jar/ear and ensuring that co-operating beans look up each other via ejb links/references. see my previous post for further details or a white paper I wrote on
EJB Design Patterns (page 20 i believe)
Reflection can be used (in fact we have a lot of projects based on it) as long as you are aware of the costs of reflection. In many cases, you want reflection to be done at start up/first access only and the results cached/reused thereafter. This may speed up things considerably.
Hi Krishnan :-)
"You cannot have EJB links between EJBs in different jars"
Actually you can if you embbed the remote and home interface of the referenced bean in the original one.
Of course tehre is no need to embedd the Bean implementation.
Regarding Reflection, it is quite fast, and I like it
especially when you think about the flexibility it brings
As you say, it is better to cache the Method object when possible. As java.lang.reflect.Method is not Serializable,
we just have to take care of the passivation in the case of SFSB.
Versioning the way I described it might be a overkill solution. I think it is worth having a 10 min upgrade
where the system is down every monday morning at 0500 for
example :-) although I find the problem interesting.
For my point of view, versioning is not the purpose of particular developement in your ejbs. Not very nice to have java code expecially for the updates.
the problem is that jars packages (& ear & war & rar ...) is that any dependancy between them could be assigned.
If I was you, (with enough time) I would write a big gaz machine using ant for versionning (the version is a text file in the jar, containing the @javadoc tags ),for deploying to your nodes, for controling the deployment.
I ve read a nice article about EJB 2 and J2EE Packaging. Tyler Jewell talks about the new J2EE 1.3 spec with jar extension (dependancy coded in the manifest file).
This feature could be improved with a versioning number.
What about having an enhancement for the J2EE IDE Toolkit (deployement according a version number)
This is an interesting topic that is also known - I believe - as "evolutionary systems". This is a link to some research on evolutionary systems:
I think that J2EE is well-positioned to provide a solution (even a partial one) to this problem, but until that happens (in the spec) my preferred approach would be to handle each migration in an ad-hoc way and live with the smallest possible downtime, and I would not use specific patterns (like using reflection) because this increases the complexity of the code.
lichtner at bway dot net
For the time being, I prefer your approach.
I would like to see this "evolutionary" behaviour addressed in the next specification. It is an interesting topic.
Thank you for the link.