views:

75

answers:

1

I've got an app that is trying to use @EJB annotation to inject remote references to EJBs in my ejb.jar file. I'm getting inconsistent results. In one case, I have a listener in web.xml that gets called and apparently has the EJB injected correctly, since I can see it connecting to the EJB and calling methods on it. In another class (a struts2 action) I get NPE when it tries to access the EJB reference. As far as I can tell, they're identical calls, in Java classes that live in the same .war file.

As a work around, I added code in the constructor to lookup the EJBs by their global JNDI names, and it works fine. I just can't figure out why one @EJB works and not another.

+2  A: 

How do you inject EJBs in Struts 2 actions? Are you using CDI? Are you using the Struts2 CDI plugin?

Update: The problem is that the container is not creating the Struts objects, Struts is, so the container doesn't get the opportunity to inject anything. You'll have to use the mentioned plugin for CDI to enable injection in your actions.

If you want to give it a try, get Struts 2 sources:

svn co http://svn.apache.org/repos/asf/struts/struts2/trunk/ struts2

Then cd into the struts2 directory and run the following command (this will compile the required modules for the struts-cdi-plugin)

mvn install -pl plugins -am

Then get the sources of the cdi-plugin:

svn co https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-cdi-plugin/

And compile it:

mvn install

Now, with the following dependencies in my pom.xml:

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>2.2.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-cdi-plugin</artifactId>
    <version>2.2.0-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.8.0.GA</version>
</dependency>

I was able to get an EJB injected in an Action:

public class HelloWorld extends ActionSupport {

    @Inject
    HelloEJB helloEjb;

    @Override
    public String execute() throws Exception {
        setMessage(helloEjb.getMessage());
        return SUCCESS;
    }

    private String message;

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}

See https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-cdi-example/ for an example.

Pascal Thivent
No, just a straight @EJB annotation.
g051051
Thanks for the explanation. This neatly explains why my listener (instantiated by the container from a web.xml entry) worked but my actions (instantiated by struts) did not. I just assumed that any annotated class would get processed via some sort of classloader voodoo. Is this sort of thing documented anywhere?
g051051
@g051051 The listener is a so called "managed" component and injection works (since Java EE 5, see http://java.sun.com/developer/technicalArticles/J2EE/intro_ee5/#injection for example). Java EE 6 goes beyond this limitation by making injection possible in any POJO using CDI (but you have to use CDI or CDI "aware" frameworks).
Pascal Thivent