Saturday, July 24, 2010

JBoss: Inject EJB from different EAR

Background
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:
@Local
public interface FooService {
public void foo();
}

@Stateless(name="FooService")
public class FooServiceBean implements FooService {
@Override
public void foo() {
/* ... */
}
}
I 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 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();
}
}

3 comments:

  1. Seems to work for me, except when having the other EAR deployed to another node in the cluster. Any experience there?

    ReplyDelete
  2. This does not seem to be working for me ;(

    Any 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!

    ReplyDelete
  3. Thanx a lot this has worked for me.

    ReplyDelete