9
votes

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?

5
The another EJB you tried to inject in, is it in the same EJB Jar or another archive ? To note: To enable bean-discovery (or CDI) beans.xml should be present in each of the deployment archives. In WEB-INF for .wars and in META-INF for .jarsstratwine
I have tried to convert my project to an ant build. Everything works fine now. I don't even need to create separate producers for war and ejb modules anymore. The question now is: Is there any problem with the maven archetype? Or are there any special caveats to consider?Philip Markus
Maybe your @Inject is not in a managed bean or other EE component that supports injection? What/where is it?covener
What bugs me is that almost the exact same code (everything is the same, except there are no producer definitions for the EJBs) works with an ant build but not with a maven build.Philip Markus

5 Answers

1
votes

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

1
votes

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.

0
votes

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.

0
votes

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).

0
votes

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