From the discussion on the Glassfish forums:
The entered link is updated only when the new instance that it introduces is created by the EJB container. Therefore, if you look at it all the time, you get an instance with an updated link, but if your code holds onto the original instance or if it is merged, the add link remains outdated.
So the root problem is that the EJB link is out of date. I found two solutions to this problem:
- Look at EJB for every request (do not use CDI)
- Wrap EJB in a proxy server that looks for EJB if the link is out of date
In the second solution, CDI can still be used. You will need a producer and an InvocationHandler . The code below is a simplified version of the code that I use in my project, and it may not compile properly, but it will show the idea and concepts used to complete this work. YMMV.
First, in code using EJB, you use @Inject , as shown below:
public class Foo { @Inject MyEjb obj; }
Secondly, you need a manufacturer that simply returns a wrapped version of EJB:
public class MyEjbProducer { @EJB(name = "MyEjb") private MyEjb obj; @Produces public MyEjb getEjb(final InjectionPoint ip) { InvocationHandler handler = new MyInvocationHandler(obj, MyEjb.class); return (MyEjb)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); } }
Thirdly, the call handler should check for NoSuchEjbException and find the bean again:
public class MyInvocationHandler implements InvocationHandler { private MyEjb obj; private Class lookupClass; public MyInvocationHandler(MyEjb obj, Class lookupClass) { this.obj = obj; this.lookupClass = lookupClass; } public Object invoke (...) { try { return method.invoke(impl, args); } catch (final InvocationTargetException e) { if (e.getTargetException() instanceof NoSuchEJBException) {
This code is by no means complete. Some of the code, such as finding an EJB and calling the method again, was omitted.
Doing this will work this way. Another method would be to do something similar, but by adding a separate EJB method to test for durability, instead of using the method that the user is trying to call.
What do you think? Is there a better solution?