4 Replies Latest reply on Apr 3, 2008 9:33 AM by ariekenb

    Re: Bug: Injected EJB objects instantiated on every MDB call

    doktora

       

      "adrian@jboss.org" wrote:
      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.


      Hi Adrian,

      Apologies for posting on the wrong forum, but the issue seems to present itself only in MDBs, therefore my assumption that it was an MDB problem. I didn't write the code, so you might be right.

      I think my understanding of pooling is pretty good, ergo the post and the "Bug" in the title. I'm pretty sure this is broken:

      After making 351 requests, how many instances of RecordManagerBean do you think were created? The answer is, 351. postConstruct was called 351 times and preDestroy was called 0 times, so none of these instances were claimed back. Is there a fault in my understanding of how this should work?

      What happened on the 352'nd request? Here:


      Can't create thread: 5
      13:34:45,519 ERROR [JmsServerSession] Unable to schedule work
      javax.resource.spi.work.WorkRejectedException: org.jboss.util.threadpool.ThreadPoolFullException: java.lang.OutOfMemoryError: unable to create new native thread
       at org.jboss.resource.work.WorkWrapper.rejected(WorkWrapper.java:250)
      ...
      



      JBoss is started with -Xms128m -Xmx512m, so maybe these memory settings will make it easier to replicate the bug.

      Here is also a script to call the calculator injection mdb 3 times every second:



      URL="http://<YOURIP>:8080/EJB3Trail/serviceobjects/injection/calculator.jsp?action=send&start=25&end=65&growthrate=0.08&saving=300&submit=Calculate"
      
      out=/dev/null
      content=/dev/null
      
      i=0
      while [ $i -ne 500 ]; do
       i=`echo "1 + $i" | bc -q`
       echo $i
       wget $URL --output-file $out --output-document $content
       wget $URL --output-file $out --output-document $content
       wget $URL --output-file $out --output-document $content
       sleep 1
      done




      Please be so kind to ponder on my comments and reconsider whether it still looks like I don't understand ejb's and pooling.

      Also consider that jaikiran independently verified this with his own code.

      Also consider the fact that this behaviour does not occur if we do not use MDB, i.e. just by using stateless beans.

      Kind regards
      Dok



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

          A little background about this thread can be found at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=132331

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

            I'm quite new to EJB3, but I can verify I see the same behavior in 4.2.2.GA of the @PostCreate method in a stateless session bean being called every time my MDB gets a message and tries to access the session bean. The JMX console also shows CreateCount growing rapidly for the session bean.

            Oddly in my setup (running my own code) I was able to get over a thousand session beans created with the standard -Xms128m -Xmx512m options to JBoss without anything failing. I was also monitoring the number of threads created by JBoss's java process and they did not seem to be growing.

            As an experiment, I modified the Stateless stanza in ejb3-aop-interceptors.xml to use StrictMaxPool instead of ThreadlocalPool:

            Original:

             <domain name="Stateless Bean">
            
             <annotation expr="!class(@org.jboss.annotation.ejb.PoolClass)">
             @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.ThreadlocalPool.class, maxSize=30, timeout=10000)
             </annotation>
            


            My test:

             <domain name="Stateless Bean">
            
             <annotation expr="!class(@org.jboss.annotation.ejb.PoolClass)">
             @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
             </annotation>
            


            After doing this I only see 2 instances of my stateless session bean created, even in tests where it's called from multiple different MDBs and directly from clients. It appears StrictMaxPool is much more conservative in ThreadlocalPool.

            doktora - Maybe using StrictMaxPool would be an interesting test/workaround in your case?

            To the JBoss experts out there - is it a "problem" that ThreadlocalPool appears to create a new instance of a stateless session bean for every call from an MDB, or is this somehow being managed? What exactly is the difference with StrictMaxPool? Will using StrictMaxPool kill performance?

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

               

              "ariekenb" wrote:
              After doing this I only see 2 instances of my stateless session bean created, even in tests where it's called from multiple different MDBs and directly from clients. It appears StrictMaxPool is much more conservative in ThreadlocalPool.

              doktora - Maybe using StrictMaxPool would be an interesting test/workaround in your case?

              To the JBoss experts out there - is it a "problem" that ThreadlocalPool appears to create a new instance of a stateless session bean for every call from an MDB, or is this somehow being managed? What exactly is the difference with StrictMaxPool? Will using StrictMaxPool kill performance?

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

              ThreadlocalPool should be used in a scenario where there is high concurrency on an EJB which is being called by a ThreadPool. The ThreadlocalPool will then ensure that there is one instance per Thread and no contention between these threads.

              It would appear that JBossMQ does not use a ThreadPool, but instantiates threads on the fly. Thus the ThreadlocalPool will keep on creating instances to match.

              That makes the use of StrictMaxPool mandatory.

              Thus only remains the issue of why ThreadlocalPool retains instances after the thread has died. ThreadlocalPool retains all instances to make sure PreDestroy is called upon destruction of the pool.
              I could implement something that PreDestroy is called when the instance is ready for GC, but in this scenario it would entail creating an instance for each MDB call. That is certainly a higher performance hit then contention in the StrictMaxPool.

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

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

                Will StrictMaxPool become the default in a the next 4.2.x release, or do we have to wait for JBoss Messaging to replace JBossMQ (version 5?)?