dependency-injectionnullpointerexceptionejbwebsphere-libertyjava-ee-8

NullpointerException while injecting by using @EJB


i have problems while injection my beans with the @EJB annotation - the beans are always null...

First, here is the relevant part of my projectstructure.

ApplEAR.ear
|
├──WebModule.war (de.example.rest)
└──EJBModule.war (de.example.service)

So... now i am trying to inject a bean from the ejbmodule in my webmodule:

de.example.rest.RestBean:

@Stateless(name = "RestBean")
@Path("/restElements")
public class RestBean implements IRestBean {
    
    @EJB
    private UserBean userBean;

de.example.service.UserBean:

@Stateless(name = "UserBean")
@TransactionManagement(TransactionManagementType.BEAN)
@LocalBean
public class UserBean{...

And in my WebModule i have this class to extend the Application-class:

@ApplicationPath("/*")
public class RestApplication extends javax.ws.rs.core.Application {
    /**
     * {@inheritDoc}
     */
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(de.example.rest.RestBean.class);
        return classes;
    }
}

The ear is deployed on a websphere liberty server with these installed features:

<feature>localConnector-1.0</feature>
<feature>appSecurity-3.0</feature>
<feature>beanValidation-2.0</feature>
<feature>ejbLite-3.2</feature>
<feature>ejbRemote-3.2</feature>
<feature>javaMail-1.6</feature>
<feature>jca-1.7</feature>
<feature>jdbc-4.2</feature>
<feature>jndi-1.0</feature>
<feature>jpaContainer-2.2</feature>
<feature>jsf-2.3</feature>
<feature>jsp-2.3</feature>
<feature>ldapRegistry-3.0</feature>
<feature>servlet-4.0</feature>
<feature>transportSecurity-1.0</feature>
<feature>websocket-1.1</feature>
<feature>jaxws-2.2</feature>
<feature>jaxrs-2.1</feature>

I tried different things to solve my problem: Creating a beans.xml in every WEB-INF/META-INF folder, trying with @LocalBean and with an @Local-interface - and injecting the interface, using @EJB(lookup = "java:global/ApplEAR/EJBModule/UserBean!de.example.service.UserBean"), using @Inject instead.

With the help of

InitialContext ctx = new InitialContext();
            Object service = ctx.lookup(java:global/ApplEAR/EJBModule/UserBean!de.example.service.UserBean);

I can lookup the bean, but it would be easier by using annotations.

So what am i missing or doing wrong?


Solution

  • I'm going to give an answer without an explanation (since I couldn't describe all the nuances of EJB vs CDI injection in JAX-RS, the specifications, etc.).

    You can get UserBean injected into RestBean by removing the EJB annotation from RestBean and adding @Dependent to convert it to a CDI-managed bean.

    // ... 
    import javax.enterprise.context.Dependent;
    
    //@Stateless(name = "RestBean")
    @Path("/restElements")
    @Dependent
    public class RestBean implements IRestBean {
    

    This assumes you don't need to use RestBean, say, as a remote EJB, and are OK with only using it as a CDI-managed bean and/or JAX-RS resource.

    (Note: This assumes you have a CDI feature enabled, which you do, transitively/indirectly).