9 Replies Latest reply on Mar 31, 2008 10:04 AM by doktora

    Bug: Injected EJB objects instantiated on every MDB call

    doktora

      It seems to me that a new instance of the EJBs injected in an MDB is created every time the MDB processes a message.

      Below is the code modifications I've made to the EJB3 Trailblazer to verify this. A RecordManagerBean object is created every time the onMessage method in the CalculatorMDB is called as can be seen from the console printout of the postConstruct method.

      This can have serious implications on memory consumption in a production environment.

      I've added the following lines to this file in the EJB3 Trailblazer source code:

      ./src/trail/injection/RecordManagerBean.java

      import javax.annotation.PostConstruct;
      import javax.annotation.PreDestroy;
      import javax.ejb.PostActivate;
      import javax.ejb.PrePassivate;
      import org.jboss.logging.Logger;


      ...

      private static final Logger log = Logger.getLogger(RecordManagerBean.class);
       @PostConstruct public void postConstruct() { log.info("++++++++++++ postConstruct +++++++++++ "); }
       @PreDestroy public void preDestroy() { log.info("preDestroy **********"); }
       @PrePassivate public void prePassivate() { log.info("prePassivate **********"); }
       @PostActivate public void postActivate() { log.info("postActivate **********"); }



      postConstruct is called on every MDB call, none of the other methods seem to be executed ever.


      Is this a bug or am I missing something?

      Cheers
      Dok


      P.S.

      JBoss [Trinity] 4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)
      Java version: 1.5.0_13,Apple Computer, Inc.
      OS-System: Mac OS X 10.4.11,i386

      JBoss is started with -c all and the EJB3Trail.jar is put in all/farm/

        • 1. Re: Bug: Injected EJB objects instantiated on every MDB call
          jaikiran

          I haven't played with MDBs on JBoss for sometime now, but are you sure the postConstruct is being called repeatedly on the *same instance* of the MDB? Or is every new message being processed by a new instance of the MDB, in which case it explains why the postConstruct gets called everytime the message is consumed.

          • 2. Re: Bug: Injected EJB objects instantiated on every MDB call
            doktora

            I'd bet my software hat on it.

            I've added some sop's to the constructors of CalculatorMDB and RecordManagerBean just to make sure that the container is playing by the rules when calling postConstruct:

            CalculatorMDB() {
             System.out.println("CalculatorMDB() CONSTRUCTOR");
             }
            
             RecordManagerBean() {
             System.out.println("RecordManagerBean::CONSTRUCTOR()");
             }
            


            And here is the output from hitting the "Calculate" button three times on /EJB3Trail/serviceobjects/injection/calculator.jsp

            17:24:06,980 INFO [STDOUT] CalculatorMDB() CONSTRUCTOR
            17:24:07,001 INFO [STDOUT] RecordManagerBean::CONSTRUCTOR()
            17:24:07,002 INFO [RecordManagerBean] ++++++++++++ postConstruct +++++++++++
            17:24:07,005 INFO [STDOUT] The onMessage() is called
            17:24:09,997 INFO [STDOUT] RecordManagerBean::CONSTRUCTOR()
            17:24:10,000 INFO [RecordManagerBean] ++++++++++++ postConstruct +++++++++++
            17:24:15,106 INFO [STDOUT] RecordManagerBean::CONSTRUCTOR()
            17:24:15,107 INFO [RecordManagerBean] ++++++++++++ postConstruct +++++++++++
            17:24:15,108 INFO [STDOUT] The onMessage() is called
            17:24:25,052 INFO [STDOUT] RecordManagerBean::CONSTRUCTOR()
            17:24:25,056 INFO [RecordManagerBean] ++++++++++++ postConstruct +++++++++++
            17:24:25,058 INFO [STDOUT] The onMessage() is called
            



            One CalculatorMDB object was created and four (?) RecordManagerBean objects.

            Doesn't seem right to me.

            cheers
            dok

            • 3. Re: Bug: Injected EJB objects instantiated on every MDB call
              doktora

              And when I say it doesn't seem right, I'm really downplaying my jaw dropping feeling on the implications of this, assuming it is what I think it is.


              • 4. Re: Bug: Injected EJB objects instantiated on every MDB call
                doktora

                I get the same result on

                JBoss [Zion] 4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)

                • 5. Re: Bug: Injected EJB objects instantiated on every MDB call
                  jaikiran

                  I do see the same behaviour on 4.2.2. Here's my MDB:

                  package org.myapp.ejb.impl;
                  
                  import javax.ejb.ActivationConfigProperty;
                  import javax.ejb.EJB;
                  import javax.ejb.MessageDriven;
                  import javax.jms.Message;
                  import javax.jms.MessageListener;
                  import javax.persistence.PostRemove;
                  
                  import org.apache.log4j.Logger;
                  import org.myapp.ejb.UserManager;
                  
                  /**
                   * MDB for testing injection of EJBs
                   *
                   * @author Jaikiran Pai
                   * @since
                   */
                  @MessageDriven(activationConfig =
                  {
                  @ActivationConfigProperty(propertyName="destinationType",
                  propertyValue="javax.jms.Queue"),
                  @ActivationConfigProperty(propertyName="destination",
                  propertyValue="queue/A")
                  })
                  public class MyMDB implements MessageListener {
                  
                   private static Logger logger = Logger.getLogger(MyMDB.class);
                  
                  
                   private UserManager userManager;
                  
                   public UserManager getUserManager() {
                   return this.userManager;
                   }
                  
                   @EJB
                   public void setUserManager(UserManager userManager) {
                   this.userManager = userManager;
                   }
                  
                   /**
                   * Default constructor
                   *
                   */
                   public MyMDB() {
                   System.out.println("In constructor of MDB");
                   }
                  
                   /**
                   *
                   */
                   public void onMessage(Message arg0) {
                   System.out.println("onMessage of MyMDB called");
                   System.out.println("EJB is " + getUserManager());
                   getUserManager().getUser((long)1);
                   logger.info("onMessage of MyMDB called");
                   }
                  
                  
                  
                  }


                  A new instance of UserManagerBean gets injected everytime the onMessage method is invoked. I just glanced through the EJB spec and did not see any mention of this behaviour being mandated. You are right, the injection should have happened only if a new instance of the MDB was created instead of injecting the EJB on every call of onMessage.

                  • 6. Re: Bug: Injected EJB objects instantiated on every MDB call
                    doktora

                    I've reported this as a bug here:

                    http://jira.jboss.org/jira/browse/JBAS-5345


                    jaikiran, what platform are you running 4.2.2 on?

                    • 7. Re: Bug: Injected EJB objects instantiated on every MDB call
                      jaikiran

                       

                      21:52:11,700 INFO [ServerInfo] Java version: 1.5.0_07,Sun Microsystems Inc.
                      21:52:11,715 INFO [ServerInfo] Java VM: Java HotSpot(TM) Server VM 1.5.0_07-b03,Sun Microsystems Inc.
                      21:52:11,715 INFO [ServerInfo] OS-System: Windows 2003 5.2,x86
                      


                      • 8. Re: Bug: Injected EJB objects instantiated on every MDB call

                        As I commented on the "bug" report. This is not JMS, this is EJB3.

                        OFF TOPIC - use the ejb3 forum rather than respond to this post.

                        It isn't clear to me what you are doing, but it doesn't look like a bug to me.
                        It looks like you don't understand that ejbs are pooled and/or that multiple copies
                        of an entity bean can exist simultanously,
                        e.g. for optimisitic locking

                        To have singletons you need to use some form of pessimistic locking which is usually not
                        very performant.

                        • 9. Re: Bug: Injected EJB objects instantiated on every MDB call
                          doktora