Philip Markus
Philip Markus

Reputation: 91

CDI Injection of an EJB leads to NullPointerException

I am new to Java EE 6 and CDI. I have read a couple of tutorials and the weld documentation. However something that should work from my understanding doesn't so I need help.

I have the following situation. I created a Java EE 6 Application with NetBeans 7.0.1 using the maven archetype supplied with the IDE and I deploy to GlassFish 3.1 also supplied by the IDE.

The beans.xml is located in the META-INF directory of my EJB jar.

I have created a class that works soley as a producer class for my EJB Artifacts (and EntityManager)

@Stateless
public class EjbArtifactProducer {

    @PersistenceContext(unitName = "trackProfiler-PU")    
    private EntityManager em;

    @EJB
    private UserFacadeLocal userFacade;

    @EJB
    private AuthServiceLocal authService;

    @EJB
    private NewsEntryFacadeLocal newsEntryFacade;

    @EJB
    private RoleFacadeLocal roleFacade;

    @EJB
    private TrackCommentFacade trackCommentFacade;

    @EJB
    private TrackFacade trackFacade;

    @EJB
    private TrackTypeFacade trackTypeFacade;

    @EJB
    private WaypointFacadeLocal waypointFacade;

    @Produces
    public AuthServiceLocal getAuthService() {
    return authService;
    }

    @Produces
    public EntityManager getEm() {
    return em;
    }

    @Produces
    public NewsEntryFacadeLocal getNewsEntryFacade() {
    return newsEntryFacade;
    }

    @Produces
    public RoleFacadeLocal getRoleFacade() {
    return roleFacade;
    }

    @Produces
    public TrackCommentFacade getTrackCommentFacade() {
    return trackCommentFacade;
    }

    @Produces
    public TrackFacade getTrackFacade() {
    return trackFacade;
    }

    @Produces
    public TrackTypeFacade getTrackTypeFacade() {
    return trackTypeFacade;
    }

    @Produces
    public UserFacadeLocal getUserFacade() {
    return userFacade;
    }

    @Produces
    public WaypointFacadeLocal getWaypointFacade() {
    return waypointFacade;
    }    

}

I tried to apply the @Produces annotation directly to the fields an on methods as shown above.

However the following does not inject anything in another EJB

@Inject
private NewsEntryFacadeLocal newsEntryFacade;

This is done in a stateless session ejb but when I try to access newsEntryFacade in any of my business methods a NullPointerException is thrown. So clearly no Injection is happening or my producers produce null references.

Am I missing something? Or should this work according to CDI/Weld?

Strangely it seems to work that way when I try to @Inject EJBs into the web application part (however i needed an extra producer class in my .war for this to work, is this as it should be?).

EDIT: The project works with an ant build (generated by NetBeans). Are there issues with the Maven archetype provided by NetBeans? It seems that with the Maven archetype there are some issues with CDI injection between the war and ejb modules. I found that if I had separate producers in the web and ejb module Glassfish generates a deployment error stating that there are two indistinguishable implementations of an interface. But when I remove the producer in the web module Weld complains that the EJB i want to inject into my beans in the web module cannot be resolved. Also with the Ant build EJBs can be @Injected without a producer while the maven build needs producer fields on a class. I can't explain how this could happen. After all the final deployment should be more or less equal, shouldn't it?

Upvotes: 9

Views: 9523

Answers (5)

StefanHeimberg
StefanHeimberg

Reputation: 1465

you are mixing two different concepts... use CDI as backing beans for JSF. (CDI in Web Container) and use EJB and JPA in the Business Layer... the CDI layer can inject a EJB to call the specific business method.

in this case you have a clean separation on concerns.

BTW: you do not need any EJB interfaces at all! use only interfaces if you have a requirements to communicate from remote... (@Remote). with the @LocalBean annotation you can inject directly the EJB itself..

if you have e clean separation of layers each with his own concern i think you better find the reason for this NullPointerException.. and i think your NullPointerException does not exists any more after this...

Layering:

Web Browser --> JSF Facelet --> CDI Backing Bean --> EJB Service(s) --> EntityManager

Upvotes: 0

lcestari
lcestari

Reputation: 178

Try to put @Named into EjbArtifactProducer. Also, if the produces is this kind of simple, I think it's better to remove it too (else, you should do one more change).

Upvotes: 0

John Manko
John Manko

Reputation: 1908

Jordan Denison is correct. You're trying to @Inject and EJB, but you be using @EJB for EJBs. You're EJB class is probably annotated with @Stateless or something. @Inject should be used on session beans that annotated with @Named and some sort of scope.

Upvotes: 1

rogergl
rogergl

Reputation: 3771

Hard to tell whats going wrong but what definitely did not work for us is to use CDI between class loader boundaries. For example if your application is packaged as an ear file you would have your ejbs in an jar file and your webapp in your war file. In this case you can not use CDI to inject your ejbs in your web layer. The problem is that the jar and the war is loaded by different class loaders. Maybe newer CDI implementations behave different but at least JBoss 6 and Glassfish had this problem.

Upvotes: 0

Jordan Denison
Jordan Denison

Reputation: 2727

If you want to use @Inject then annotate it as @Named @ApplicationScoped, otherwise use @EJB when injecting your singleton.

Upvotes: 1

Related Questions