3

I am somewhat new to Java EE (dependency injection) and I can't figure out why @Inject is giving me null, yet InitialContext.doLookup does work.

Here is my bean. It is just a DAO. A wrapper for EntityManager basically

@Stateless
public class PersonManager {
    @PersistenceContext("unitName="PersonData")
    EntityManager em;
...
}

Here is a REST service, where I am trying to utilize PersonManager:

@Path("/PersonService")
@RequestScoped
public class PersonService {
    @Inject private PersonManager manager; //this comes up null

    @GET
    @Produces("text/html")
    public String getAllPersons() {
        List<Person> personList manager.findAll(); //null pointer exception, manager null
    }
}

Now what is weird is, if I do a lookup on PersonManager, it does work, like this:

@GET
@Produces("text/html")
public String getAllPersons() {
    try {
        manager = InitialContext.doLookup("java:global/PersonApp/PersonData/PersonManager");
    }
    catch(Exception e) {
        e.printStackTrace();
    }

    List<Person> personList manager.findAll(); //this works!
}

Any idea why @Inject doesn't work here? I am using an EAR with a WAR and JAR within it like this:

EAR (PersonApp)

--JAR (PersonData - ejb module - contains PersonManager)

--WAR (PersonRest - web module - contains PersonService)

dave823
  • 1,191
  • 2
  • 15
  • 32
  • OK. In EE 6 you needed an empty beans.xml in order for CDI to kick in. Shouldn't be required in EE 7 though. – JHollanti Mar 31 '14 at 19:21
  • Thanks. I do not have a beans.xml currently. I was told it is not required for EE7 and CDI 1.1 – dave823 Mar 31 '14 at 19:22
  • Might have something to do with injecting in WAR? – JHollanti Mar 31 '14 at 19:24
  • I am using a WAR but I don't know if that has is an issue or not. I am using an EAR, and within that a WAR (web module) and a JAR (ejb module). The REST service is in the WAR, and PersonManager is in the JAR. – dave823 Mar 31 '14 at 19:30
  • Try the empty beans.xml first. I had similar problems with GlassFish4, which is presumably EE7, and adding empty beans.xml enabled @Inject annotation. – Oleg Estekhin Mar 31 '14 at 19:31
  • Also, did you try these three ways: http://stackoverflow.com/questions/3027834/inject-a-ejb-into-jax-rs-restfull-service – JHollanti Mar 31 '14 at 19:34
  • @OlegEstekhin I tried adding beans.xml but it didn't seem to make a difference – dave823 Mar 31 '14 at 19:39
  • @JHollanti I have tried options 2 and 3 in that list. I have not tried creating my own injection provider (option 1), but I was hoping I wouldn't have to do that – dave823 Mar 31 '14 at 19:41
  • 1
    Ok, did you make sure PersonService is not a singleton? Check @Martin's answer on that same question. – JHollanti Mar 31 '14 at 19:42
  • ah thanks that was it! Eclipse automatically added in a line "singletons.add(new PersonService());" If I comment out this line it works. Any idea why this works, and why Eclipse would generate that automatically when you create a REST service? – dave823 Mar 31 '14 at 19:47
  • 'Cause Eclipse sucks :) https://www.jetbrains.com/idea/ – JHollanti Mar 31 '14 at 19:50
  • I remember NB doing something similar. I didn't know that Eclipse does it too. You probably have some fancy plugin installed that tries to guess what you want. – JHollanti Mar 31 '14 at 19:51
  • 1
    As to why it works is because if it's a Singleton then it's somehow not managed by the container and nothing will get injected. @Martin gave a pretty good explanation of it also. – JHollanti Mar 31 '14 at 19:52
  • @OlegEstekhin The behavior of CDI changed in Java EE 7. See http://stackoverflow.com/questions/18310388/meaning-of-bean-discovery-mode-annotated-in-cdi-1-1/18323511#18323511 for more information on how to include beans.xml and still have the container scan for classes. – Ian Evans Apr 01 '14 at 18:57

1 Answers1

0

The problem turned out to be adding PersonService as a singleton in the rest application registration.

@ApplicationPath("api")
public class RestApplication extends Application{

    private Set<Object> singletons = new HashSet<Object>();
    private Set<Class<?>> empty = new HashSet<Class<?>>();
    public RestApplication(){
         //below line caused @Inject not to work. commented out
         //singletons.add(new PersonService());  
    }
    @Override
    public Set<Class<?>> getClasses() {
         return empty;
    }
    @Override
    public Set<Object> getSingletons() {
         return singletons;
    }
}
dave823
  • 1,191
  • 2
  • 15
  • 32