CDI not working in objects created from factory pattern implementation

Viewed 1021

I am trying to wrap my head around something here: Injection only works on the first layer of my application, but then it stops and all @Inject annotated properties are null in the objects returned from my factory pattern implementation. I read a lot about people having problems with getting CDI to work with JAX-RS but this seems not to be my problem. I have the feeling that I am missing some annotations, or I don't see the wood in front of all the trees (as we say here) ;-)

Edit: Did a sample project with the code I posted here to double check. Now I realise that I over simplified: in fact I am using a Factory Pattern to obtain my service, which might interrupt the managed context. Please see the augmented example:

Let's go.

First Layer: JAX-RS Application, all good

@RequestScoped
@Path("/somePath/someResource")
public class SomeResource {
   @Inject
   ISomeServiceFactory someServiceFactory;

   @POST
   @Produces(MediaType.APPLICATION_JSON)
   @Consumes(MediaType.APPLICATION_JSON)
   public SomeResponse someMethod(@PathParam("foo") final String foo) {
      ISomeService myService = someServiceFactory.getService(ServiceCatalog.valueOf(foo));   // works, we jump in there!
      myService.someMethod();
   }

}

public enum ServiceCatalog {
  STANDARD("standard"), ADVANCED("advanced"), FOO("foo");
  // ...
} 

The broken service factory that is selecting an implementation based of known parameter (Enum) values from the REST API Call:

public interface ISomeServiceFactory {
  public ISomeService getService(ServiceCatalog serviceType);
} 

@Stateless
public class SomeServiceFactory implements ISomeServiceFactory {
  public ISomeService getService(ServiceCatalog serviceType) {
    if(serviceType.equals(ServiceCatalog.FOO)) {
      return new FooService();  // will break CDI context
    } else if (...) {
      // ...
    } else {
      return new DefaultService(); // will also break CDI context
    }
  }
}

Second Layer: Some EJB, trouble here

// Interface: 

public interface ISomeService {
  public void someMethod();
}

// Implementation:

@Stateless
public class SomeService implements ISomeService {
  @Inject
  private ISomeDao someDao;    // this will be null !!!

  @Override
  public void someMethod() {
    someDao.doSomething()   // exception thrown as someDao == null
  }
}

The Dao that is supposed to be injected

public interface ISomeDao {
  public void someMethod();
}

@Stateless
public class SomeDao implements ISomeDao {
  public void someMethod() {}
}

Now at runtime WebSphere Liberty tells me (among other bindings...) this:

 com.ibm.ws.ejbcontainer.runtime.AbstractEJBRuntime
 I CNTR0167I: The server is binding the com.ISomeDao interface of the
 SomeDao enterprise bean in the my.war module of the my application.  
 The binding location is: java:global/my/SomeDao!com.ISomeDao

I have a beans.xml:

 <beans
   xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee    http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
   bean-discovery-mode="all">
 </beans>

It seems as if the new SomeService() breaks everything, could you advice on how to implement the factory in a way that enables CDI further down the road? Thanks.

1 Answers
Related