7 Replies Latest reply on Jan 18, 2007 11:11 AM by Ian Hlavats

    Stack Overflow using EJB3

    iwadasn Newbie

      I get a stack overflow while passivating my Stateful bean....

      10:46:15,257 INFO [STDOUT] Exception in thread "Timer-7"
      10:46:15,258 INFO [STDOUT] java.lang.StackOverflowError
      10:46:15,270 INFO [STDOUT] at java.util.Hashtable.get(Hashtable.java:336)
      10:46:15,271 INFO [STDOUT] at java.util.Properties.getProperty(Properties.java:774)
      10:46:15,271 INFO [STDOUT] at org.jboss.util.property.PropertyMap.getProperty(PropertyMap.java:627)
      10:46:15,271 INFO [STDOUT] at java.lang.System.getProperty(System.java:629)
      10:46:15,271 INFO [STDOUT] at org.jboss.system.JBossRMIClassLoader.getClassAnnotation(JBossRMIClassLoader.java:105)
      10:46:15,271 INFO [STDOUT] at java.rmi.server.RMIClassLoader.getClassAnnotation(RMIClassLoader.java:364)
      10:46:15,271 INFO [STDOUT] at sun.rmi.server.MarshalOutputStream.annotateClass(MarshalOutputStream.java:75)
      10:46:15,272 INFO [STDOUT] at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1168)
      10:46:15,272 INFO [STDOUT] at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1121)
      10:46:15,272 INFO [STDOUT] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1278)
      10:46:15,272 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
      10:46:15,272 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
      ......
      10:46:15,527 INFO [STDOUT] at org.jboss.ejb3.stateful.StatefulBeanContext.writeExternal(StatefulBeanContext.java:120)
      10:46:15,527 INFO [STDOUT] at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1304)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1282)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1369)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1341)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)
      10:46:15,528 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
      10:46:15,529 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
      10:46:15,529 INFO [STDOUT] at java.rmi.MarshalledObject.(MarshalledObject.java:92)
      10:46:15,529 INFO [STDOUT] at org.jboss.ejb3.stateful.StatefulBeanContext.writeExternal(StatefulBeanContext.java:120)
      10:46:15,529 INFO [STDOUT] at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1304)
      10:46:15,529 INFO [STDOUT] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1282)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1369)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1341)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
      10:46:15,530 INFO [STDOUT] at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
      10:46:15,531 INFO [STDOUT] at java.rmi.MarshalledObject.(MarshalledObject.java:92)
      10:46:15,531 INFO [STDOUT] at org.jboss.ejb3.stateful.StatefulBeanContext.writeExternal(StatefulBeanContext.java:120)
      10:46:15,531 INFO [STDOUT] at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1304)
      3169.290: [Full GC 3169.290: [CMS3170.268: [CMS-concurrent-mark: 0.978/60.972 secs]


      Here is the actual code in question.....


      /*
      * Ejb3AdditionBean.java
      *
      * Created on July 15, 2005, 9:20 AM
      *
      * To change this template, choose Tools | Options and locate the template under
      * the Source Creation and Management node. Right-click the template and choose
      * Open. You can then make changes to the template in the Source Editor.
      */
      package com.hb.dataBinding.service.instrument.session;

      import javax.ejb.Remote;
      import java.util.Properties;
      import javax.ejb.Stateless;
      import javax.ejb.Stateful;
      import javax.ejb.TransactionAttribute;
      import javax.ejb.TransactionAttributeType;
      import javax.naming.InitialContext;
      import javax.persistence.EntityManager;
      import javax.persistence.EntityManagerFactory;
      import javax.persistence.PersistenceContext;
      import javax.persistence.PersistenceUnit;
      import com.hb.dataBinding.api.instrument.session.Access;
      import com.hb.dataBinding.service.instrument.entity.Ejb3InstrumentTypeImplBean;
      import javax.annotation.Resource;
      import javax.ejb.SessionContext;


      /**
      * @author tward
      */
      @Stateful
      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      @Remote(Access.class)
      public class Ejb3InstrumentAccessBean implements Access, java.io.Serializable {

      @Resource
      SessionContext _context;

      @PersistenceContext(unitName="datawarehouse")
      private EntityManager manager;

      /**
      * Creates a new instance of Ejb3AdditionBean
      */
      public Ejb3InstrumentAccessBean() { }


      public static void main( String[] args ) throws Exception {

      Properties env = new Properties();
      env.put( "java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" );
      env.put( "java.naming.provider.url", "https://" + args[0] + ":8443/invoker/JNDIFactory" );
      env.put( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" );
      //env.put( "org.jboss.security.ignoreHttpsHost", "true" );

      InitialContext ctx = new InitialContext( env );
      Access calculator = (Access) ctx.lookup( Access.class.getName() );

      System.out.println( "1 + 1 = " + calculator.add( 1, 1 ) );
      //System.out.println("1 - 1 = " + calculator.subtract(1, 1));

      }


      public double add( double x, double y ) {

      final Ejb3InstrumentTypeImplBean bean = manager.find( Ejb3InstrumentTypeImplBean.class, new Integer( 4 ) );

      System.out.println( "Got a bean: " + bean );

      return x + y;
      }

      }


      As you can see, it's based on your example code. ;-)

        • 1. Re: Stack Overflow using EJB3
          evrim ulu Newbie

          thnx, workaround fixed %100 cpu utilization problem. It was timer-5 thread for me which gives stackoverflow.

          • 2. Re: Stack Overflow using EJB3
            aycanirican Newbie

            Thank you, we're having exactly the same problem. While googling, we saw your jira entry: http://jira.jboss.com/jira/browse/EJBTHREE-231.

            After setting sessioncontext to @Transient it works like a charm.

            @Resource
            @Transient
            javax.ejb.SessionContext ctx;
            


            By the way, I bet nobody uses EJB3 SFSBs except us. That's interesting...

            • 3. Re: Stack Overflow using EJB3
              aycanirican Newbie

              Sorry it should be:

              @Resource
              private transient javax.ejb.SessionContext ctx;
              


              "aycanirican" wrote:

              After setting sessioncontext to @Transient it works like a charm.
              @Resource
              @Transient
              javax.ejb.SessionContext ctx;
              



              • 4. Re: Stack Overflow using EJB3
                evrim ulu Newbie

                In fact it was:

                @Resource
                private transient javax.ejb.SessionContext ctx;
                


                I have applied this fix also to

                @PersistenceContext(unitName = "postgresql")
                private transient EntityManager manager;
                


                I'm not sure if it's necessary too, but it's working for now.


                • 5. Re: Stack Overflow using EJB3
                  Joachim Van der Auwera Expert

                  Are you sure this works? (yes we make a lot of use of SFSB as well)

                  In my testt, if you make the entitymanager transient it is not filled in again on the bean activation. If the beans are only passivated to be removed because inactive too long, then I think you are not removing all your sfsb's after use.

                  I have read notes saying that passivating the entitymanager is fine (probably makes all the entities detached). Of course, if there are too many entities in there, you could get problems. This could be solved by flushing the session in the passivation call.

                  Joachim

                  • 6. Re: Stack Overflow using EJB3
                    evrim ulu Newbie

                    ok, you are right. How do we make prePassivate() transactional?

                    i) with @TransactionAttribute() annotation
                    ii)

                    manager.getTransaction().begin();
                    manager.flush();
                    manager.getTransaction().commit();
                    


                    I'm confused with this problem. I've tried both but failed.

                    Thnx.

                    • 7. Re: Stack Overflow using EJB3
                      Ian Hlavats Newbie

                      Hey guys,

                      Looks like this is still an issue for EJB3 / JBoss 4.0.5 GA.

                      Not sure why, the EJB3 spec clearly says (emphasis added):

                      4.2.1 Instance Passivation and Conversational State
                      
                      The Bean Provider is required to ensure that the PrePassivate method leaves the instance fields and the fields of its associated interceptors ready to be serialized by the container. The objects that are assigned to the instance?s non-transient fields and the non-transient fields of its interceptors after the PrePassivate method completes must be one of the following.
                      
                      - A serializable object.
                      - A null.
                      - A reference to an enterprise bean?s business interface.
                      - A reference to an enterprise bean?s remote interface, even if the stub class is not serializable.
                      - A reference to an enterprise bean?s remote home interface, even if the stub class is not serializable.
                      - A reference to an entity bean?s local interface, even if it is not serializable.
                      - A reference to an entity bean?s local home interface, even if it is not serializable.
                      - A reference to the SessionContext object, even if it is not serializable.
                      - A reference to the environment naming context (that is, the java:comp/env JNDI context)
                      or any of its subcontexts.
                      - A reference to the UserTransaction interface.
                      - A reference to a resource manager connection factory.
                      - A reference to a container-managed EntityManager object, even if it is not serializable.
                      
                      ...
                      


                      I'm seeing a lot of stack traces during SFSB passivation, but most of the time the app server just hangs.

                      The transient SessionContext did not work for me. Not sure what the problem is.

                      Hmm...