5 Replies Latest reply on Aug 8, 2009 10:34 AM by kapitanpetko

    EntityManager injection in a Message Driven Bean

    chrisouellette

      I am running an EJB3 Message Driven Bean and I would like to inject Application scoped seam components as well as an EntityManager instance but anything I inject with the @In annotation is coming in as null. I've scoured the boards to see if anyone is having a similar problem but I can't find anything.


      My MDB class:



      @Name("myMDB")
      @MessageDriven(activationConfig = { 
                      @ActivationConfigProperty(propertyName = "destinationName", propertyValue = "jms/myQueue"),
                      @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
      public class MyMDB implements MessageListener {
      
          @Logger
          private Log log;
          
          @In
          EntityManager localEntityManager;
          
          @In
          private MyApplicationScopedComponent myAppComponent;
      
          public void onMessage(Message message) {
      // Messages are being picked up but
      // localEntityManager and myAppComponent are null
      }
      }



      Am I missing something here? My understanding of Seam MDB's is that Application scoped components can be injected into MDB's. And what about EntityManager? I've tried using @PersistenceContext to get the EntityManager but that doesn't work either.


      I've tried debugging and I don't have an ApplicationContext.


      My environment:
      Seam 2.1.2 (and I just tried Seam 2.2.0)
      WebSphere 6.1


      Any help would be appreciated. Thanks,


      -Chris

        • 1. Re: EntityManager injection in a Message Driven Bean
          lvdberg

          Hi Chris,


          I took me a while to get things working, but it works with me. Be aware that you must define the SEAM interceptor somewher. I do this in the ejb-jar.xml file (under META-INF).


          It content should be:


          <?xml version="1.0" encoding="UTF-8"?>
          <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
                   version="3.0">
             <interceptors>
                <interceptor>
                   <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
                </interceptor>
             </interceptors>
             <assembly-descriptor>
                <interceptor-binding>
                   <ejb-name>*</ejb-name>
                   <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
                </interceptor-binding>
             </assembly-descriptor>
          </ejb-jar>



          Furthermore you must have your beans annotated with @Name as you already did and @JndiName (the latter can be done with a pattern in components.xml). I use it to send Seam events after receiving a Meeasge through JMS. Works great with Seam 2.1.2 and JBOSS 5.1


          Leo





          • 2. Re: EntityManager injection in a Message Driven Bean
            chrisouellette

            Hi Leo,


            Thanks for your reply. I do have the Seam Interceptors defined in my ejb-jar.xml and I am convinced that WebSphere is once again the cause of any problem. The good news is that I was able to get this working, albeit with a non-standard configuration. I had to make 2 concessions:



            1. I had to use a stateless session bean instead of a POJO

            2. I had to inject the bean using @EJB instead of @In



            So now, my MDB code looks like this:


            @Name("myMDB")
            @MessageDriven(activationConfig = { 
                            @ActivationConfigProperty(propertyName = "destinationName", propertyValue = "jms/myQueue"),
                            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
            public class MyMDB implements MessageListener {
            
                @Logger
                private Log log;
                
                @EJB
                private MyApplicationScopedSessionBean myAppComponent;
            
                public void onMessage(Message message) {
                     myAppComponent.doStuff();
            }
            }



            I'm actually OK with this setup. I can't use the EntityManager inside my MDB but I have full access to all Application scoped components, including EntityManager, in my session bean.

            • 3. Re: EntityManager injection in a Message Driven Bean
              dgomesbr
              Chris, like interceptors, u can't inject directly on mdb.

              try

              entityManager = (EntityManager) Component.getInstance("entityManager");


              • 4. Re: EntityManager injection in a Message Driven Bean
                chrisouellette

                Hi Diego,


                Thanks for the response. I have tried using:


                Component.getInstance("entityManager");



                from inside the MDB, but I get an exception:


                java.lang.IllegalStateException: No application context active



                • 5. Re: EntityManager injection in a Message Driven Bean
                  kapitanpetko

                  Why not just use the EJB PersitenceContext:


                  @PersistenceContext
                  EntityManager em;
                  



                  The SPMC is not really useful in and MDB (since there is no conversation).