9 Replies Latest reply on Mar 23, 2006 3:16 PM by Russ Loucks

    A CMR collection may only be used within the transction in w

    Julien Martin Expert

      Hello,

      I am running into the following problem (see exception stack below). I have not been able to establish what the problem is. I tried setting all transaction attributes to "supports" and then to "Required" and nothing seems to work. Can anyone help?

      My sources are here http://www.parispano.org/test_guide/

      type Exception report
      
      message
      
      description The server encountered an internal error () that prevented it from fulfilling this request.
      
      exception
      
      org.apache.jasper.JasperException: RuntimeException; CausedByException is:
       A CMR collection may only be used within the transction in which it was created
       org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:372)
       org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
       org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
       javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
       com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:322)
       com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:147)
       com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:87)
       com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)
       com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:117)
       javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
      
      root cause
      
      javax.ejb.EJBException: RuntimeException; CausedByException is:
       A CMR collection may only be used within the transction in which it was created
       org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:357)
       org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
       org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
       org.jboss.ejb.EntityContainer.internalInvoke(EntityContainer.java:522)
       org.jboss.ejb.Container.invoke(Container.java:871)
       org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:394)
       org.jboss.ejb.plugins.local.EntityProxy.invoke(EntityProxy.java:44)
       $Proxy177.getAverageGrade(Unknown Source)
       com.softwareag.test_guide.ejb.util.PGConvertUtil.convertPGEstablishmentLocalIntoPGEstablishmentTO(PGConvertUtil.java:20)
       com.softwareag.test_guide.sessionFacadeEJB.PGSessionFacadeBean.getEstablishmentFromId(PGSessionFacadeBean.java:38)
       sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       java.lang.reflect.Method.invoke(Method.java:324)
       org.jboss.invocation.Invocation.performCall(Invocation.java:345)
       org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:214)
       org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
       org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:113)
       org.jboss.webservice.server.ServiceEndpointInterceptor.invoke(ServiceEndpointInterceptor.java:51)
       org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
       org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:105)
       org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:342)
       org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:149)
       org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:128)
       org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
       org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
       org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:625)
       org.jboss.ejb.Container.invoke(Container.java:871)
       org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:394)
       org.jboss.ejb.plugins.local.StatelessSessionProxy.invoke(StatelessSessionProxy.java:82)
       $Proxy195.getEstablishmentFromId(Unknown Source)
       com.softwareag.test_guide.web.temp.PGBusinessDelegate.getEstablishmentFromId(PGBusinessDelegate.java:23)
       com.softwareag.test_guide.web.tags.PGSetEstablishmentTag.doStartTag(PGSetEstablishmentTag.java:27)
       org.apache.jsp.displayItem_jsp._jspService(displayItem_jsp.java:91)
       org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
       javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
       org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
       org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
       org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
       javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
       com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:322)
       com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:147)
       com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:87)
       com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)
       com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:117)
       javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
      
      note The full stack trace of the root cause is available in the Apache Tomcat/5.0.27-dev logs.
      


        • 1. Re: A CMR collection may only be used within the transction
          Collin Novice

          This is caused by, well, usually, executing some method that obtains a collection of entities within the context of a transaction, and then another method (possibly the calling method) using that collection within

          * a transaction (if the collection was obtained without a transaction)
          * no transaction (if the collection was obtained with a transaction)
          * a transaction (if the collection was obtained with a different transaction)

          What you need to do is first to figure out where exactly in your code that this is happening.

          Then, you need to figure out, right before your error, what your transactional status is. You can use this helper class to aid you:

          import javax.naming.InitialContext;
          import javax.transaction.Status;
          import javax.transaction.TransactionManager;
          
          
          /**
           * @author Collin VanDyck
           *
           */
          public class TransactionInfo {
          
           public static final boolean inActiveTransaction()
           {
           try
           {
           TransactionManager tm = (TransactionManager) new InitialContext().lookup("java:/TransactionManager");
           int status = tm.getStatus();
           if (status == Status.STATUS_ACTIVE)
           {
           return true;
           }
           }
           catch (Exception e)
           {
           e.printStackTrace();
           }
           return false;
           }
          
           public static final int getTransactionStatus()
           {
           try
           {
           TransactionManager tm = (TransactionManager) new InitialContext().lookup("java:/TransactionManager");
           int status = tm.getStatus();
           return status;
           }
           catch (Exception e)
           {
           e.printStackTrace();
           return -1;
           }
           }
          
           public static final String getTransactionInformation()
           {
           String result = "";
          
           try
           {
           TransactionManager tm = (TransactionManager) new InitialContext().lookup("java:/TransactionManager");
           int status = tm.getStatus();
          
           switch (status)
           {
           case Status.STATUS_ACTIVE:
           result = "ACTIVE";
           break;
           case Status.STATUS_COMMITTED:
           result = "COMMITTED";
           break;
           case Status.STATUS_COMMITTING:
           result = "COMMITTING";
           break;
           case Status.STATUS_MARKED_ROLLBACK:
           result = "MARKED_ROLLBACK";
           break;
           case Status.STATUS_NO_TRANSACTION:
           result = "NO_TRANSACTION";
           break;
           case Status.STATUS_PREPARED:
           result = "PREPARED";
           break;
           case Status.STATUS_PREPARING:
           result = "PREPARING";
           break;
           case Status.STATUS_ROLLEDBACK:
           result = "ROLLEDBACK";
           break;
           case Status.STATUS_ROLLING_BACK:
           result = "ROLLING_BACK";
           break;
           case Status.STATUS_UNKNOWN:
           result = "UNKNOWN";
           break;
           default:
           result = "UNDEFINED";
           }
           }
           catch (Exception e)
           {
           result = "ERROR: could not get tx status: " + e.getMessage();
           }
          
           return result;
           }
          
          }
          


          Using this class, you should be able to figure out more about what's going on.l



          • 2. Re: A CMR collection may only be used within the transction
            Jared Rodriguez Newbie

            You can actually see this problem from one line of code to the next if you are not in a transaction. For instance, if you have a BeanManaged SessionBean and forgot to grate a transaction and have a method that calls:

            . . .

            Collection c = myEntity.getCMREntities();
            Iterator i = c.iterator();

            . . .

            You will get the exception. Be sure your session beans are either container managed or that you are definately establishing a transaction before calling entitybeans. A good way to track down these problems is to set your entity beans to have "Mandatory" as the transaction attribute. Then you will know for sure where they are being accessed outside of a transaction :)

            Jared

            • 3. A CMR collection may only be used within the transction in w
              Julien Martin Expert

              Hello JCR,

              I set all my entity beans at Mandatory and I get exactly the same exception i.e.

              java.lang.IllegalStateException: A CMR collection may only be used within the transction in which it was created
               org.jboss.ejb.plugins.cmp.jdbc.bridge.RelationSet.getIdList(RelationSet.java:66)
               org.jboss.ejb.plugins.cmp.jdbc.bridge.RelationSet.access$000(RelationSet.java:32)
               org.jboss.ejb.plugins.cmp.jdbc.bridge.RelationSet$1.<init>(RelationSet.java:355)
               org.jboss.ejb.plugins.cmp.jdbc.bridge.RelationSet.iterator(RelationSet.java:353)
               org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(Unknown Source)
               org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(Unknown Source)
               org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(Unknown Source)
               javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(Unknown Source)
               org.apache.jsp.displayItem_jsp._jspx_meth_c_forEach_0(displayItem_jsp.java:282)
               org.apache.jsp.displayItem_jsp._jspx_meth_f_view_0(displayItem_jsp.java:157)
               org.apache.jsp.displayItem_jsp._jspService(displayItem_jsp.java:97)
               org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
               javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
               org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
               org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
               org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
               javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
               com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:322)
               com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:147)
               com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:87)
               com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)
               com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:117)
               javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
              


              All my beans are container managed.

              Have you got any other idea?

              Julien.

              • 4. Re: A CMR collection may only be used within the transction
                Julien Martin Expert

                Hello Collin,
                Thanks for the reply. Can you give a hint as to how to use your class please?
                Julien.

                • 5. Re: A CMR collection may only be used within the transction
                  Collin Novice

                  Sure, just use the getTransactionInformation() method right before you obtain your CMR collection to determine whether or not you are in a transaction.

                  • 6. Re: A CMR collection may only be used within the transction
                    Julien Martin Expert

                    Hello Collin,

                    I added the following line in my session facade's method:

                    logger.info(TransactionInfo.getTransactionInformation());
                    

                    and it says "ACTIVE" which means that my session facade runs within a transaction. Right?

                    The source for my session facade bean is here:
                    http://www.parispano.com/test_guide/ejb_tier/src/com/softwareag/test_guide/sessionFacadeEJB/

                    From your post I understand that the problem is either
                    -I obtain the collection WITHIN a transaction and use it WITHOUT a transaction
                    -I obtain the collection WITHOUT a transaction and use it WITHIN a transaction
                    Right?

                    What do you suggest I do to solve the problem?

                    Julien.

                    • 7. Re: A CMR collection may only be used within the transction
                      Alexey Loubyansky Master

                      You should always access entity beans in a transaction. And then make sure that you get a CMR collection and work on it in the same tx.

                      • 8. Re: A CMR collection may only be used within the transction
                        erich_lol Newbie

                        @alex

                        I am sorry but does not the J2EE spec say that transaction handling for CMP is the job of the Container?
                        By stating the desired Transactional behaviour in the deployment descriptor the container should take care of this matter.

                        As previously mentioned, entity beans that use EJB 2.0 container-managed persistence can only use Required, RequiresNew, or Mandatory transaction attributes for most business methods and methods on the home interface. Because accessing the container-managed persistence (CMP) and container-managed relationship (CMR) fields of an entity bean requires transactions, the Mandatory transaction attribute should be used for all get and set methods of an entity bean's CMP and CMR fields