I am currently working on a project using a Java EE 5 application running on JBoss 5.1. I was looking for a way to split this app up into multiple smaller parts to decouple things and to achieve a better modularity. Unfortunately I couldn't find any straight-forward answer to the question:
How to inject an EJB into another EJB if both do not reside in the same EAR?
After spending a couple of hours on research I figured out how to do this and would like to summarize the result hoping that others facing this problem may find this posting helpful.
Let's start...
First of all I start by creating the first EAR file containing the following local-interface and SLSB:
@LocalI package these files into the archive Foo.jar which in turn will be included into the first EAR called Foo.ear (including an appropriate descriptor
public interface FooService {
public void foo();
}
@Stateless(name="FooService")
public class FooServiceBean implements FooService {
@Override
public void foo() {
/* ... */
}
}
resources/application.xml
).Next I want to create a second EAR (Bar.ear) which depends upon the one I just packaged. Again there is a local-interface and the appropriate SLSB - both stored within Bar.ear:
@Local
public interface BarService {
public void bar();
}
@Stateless(name="BarService")
public class BarServiceBean implements BarService {
@Override
public void bar() {
/* ... */
}
}
Problem with injection
Now I would like to use FooService (contained in Foo.ear) from my BarServiceBean (contained in Bar.ear). A simple injection like the following
@EJB
private FooService fooService;
is not sufficient and will result in an exception when deploying the Bar.ear:
[org.jboss.kernel.plugins.dependency.AbstractKernelController] (HDScanner) Error installing to Start: name=jboss.j2ee:ear=Bar.ear,jar=Bar.jar,name=BarService,service=EJB3 state=Create
java.lang.NullPointerException
at org.jboss.ejb3.proxy.factory.ProxyFactoryHelper. getRemoteAndBusinessRemoteInterfaces(ProxyFactoryHelper.java:613)
The solution
The dependency to FooService cannot be resolved as it resides in a different EAR file. Therefore I must point my finger to the other EAR when trying to inject the EJB (watch the @EJB annotation):
@Stateless(name="BarService")
public class BarServiceBean implements BarService {
@EJB(mappedName="Foo/FooService/local")
private FooService fooService;
@Override
public void bar() {
this.fooService.foo();
}
}
Seems to work for me, except when having the other EAR deployed to another node in the cluster. Any experience there?
ReplyDeleteThis does not seem to be working for me ;(
ReplyDeleteAny idea why i would be getting this ?
" Servlet /GoodByeJohnWeb threw load() exception: java.lang.IllegalArgumentException: Can not set za.co.gbj.UserFacadeService field za.co.gbj.InjectionTest.service to za.co.gbj.UserFacadeService$$$view66
"
This is in Jboss AS 7?
Thanks forthe article!
Thanx a lot this has worked for me.
ReplyDelete