14 Replies Latest reply on Apr 29, 2003 11:52 AM by Tim Paulson

    [Jboss3.0.2] A CMR collection may only be used within the tr

    Adrian Hallam Newbie

      I have an application that worked in JBoss 3.0.0 and I moved to 3.0.2 to try and fix an unrelated problem.

      Now my existing code is giving me the following error:
      java.lang.IllegalStateException: A CMR collection may only be used within the transction in which it was created

      I have two CMP Entity Beans (User and Roles). These are connected with a Many to Many relationship.

      My ejb-relationship looks like:

      <ejb-relation>
      <ejb-relation-name>User-Role</ejb-relation-name>
      <ejb-relationship-role>
      <ejb-relationship-role-name>user-has-roles</ejb-relationship-role-name>
      Many

      <relationship-role-source>
      <ejb-name>UserEJB</ejb-name>
      </relationship-role-source>

      <cmr-field>
      <cmr-field-name>roles</cmr-field-name>
      <cmr-field-type>java.util.Collection</cmr-field-type>
      </cmr-field>
      </ejb-relationship-role>

      <ejb-relationship-role>
      <ejb-relationship-role-name>role-has-users</ejb-relationship-role-name>
      Many

      <relationship-role-source>
      <ejb-name>RolesEJB</ejb-name>
      </relationship-role-source>

      <cmr-field>
      <cmr-field-name>users</cmr-field-name>
      <cmr-field-type>java.util.Collection</cmr-field-type>
      </cmr-field>
      </ejb-relationship-role>
      </ejb-relation>


      In all the CMP examples I have looked at no one seems to play with the transactions directly - which seems to be what this thread is suggesting? I have both EJB's in <container-transaction> section and <trans-attribute> set to Required.

      The code snippet is:

      // OK
      UserLocalHome myUserHome = getUserLocalHome();
      UserLocal myUser = myUserHome.findByPrimaryKey(username);

      // OK
      RolesLocalHome myRoleHome = getRolesLocalHome();
      RolesLocal myRole = myRoleHome.findByName(roleName);

      // Exception thrown on this line
      if( myUser.getRoles().contains(myRole) ) {


      I have spent many hours searching forums, etc. but I wouldn't be suprised if I'm just doing something stupid...

      Any advice would be greatly appreciated.

      Regards,
      Adrian

        • 1. Re: [Jboss3.0.2] A CMR collection may only be used within th
          Andrew Bachelard Newbie

          Hi all,
          I am having exactly the same problem.
          I have a one-many relationship between two CMP entity beans (NewsCategory and NewsArticle). I am doing simple relationship stuff, getting all the NewsCategorys, and then calling getNewsArtcles() on each.
          Transactions are set to Required and commit-option is 'A'.
          All of which worked perfectly on 3.0.0, but fails with the IllegalStateException on 3.0.1 and 3.0.2.
          I too have spent many hours trawling through forums and source code to no avail.
          I too would not be surprised if I were doing something stupid.

          If anyone has any clues, please let me know.
          Andrew

          PS Thanks Adrian, it is very nice to know I'm not alone on this one.

          • 2. Re: [Jboss3.0.2] A CMR collection may only be used within th
            Colin Yates Newbie

            I also have this issue, but it is only an issue if I have heavy concurrent use.

            If you don't use commit option A then the problem seems to go away. It did for me.

            Now everything works, although I sometimes get transactional deadlock under heavy load.

            Hope this helps.

            • 3. Re: [Jboss3.0.2] A CMR collection may only be used within th
              Adrian Hallam Newbie

              Thanks for your reply. I have now tried every commit option A-D.

              For people who are reading along this thread who are at the same learning stage as me (newby), info can be found in the documentation (JBossBook_236.pdf) on page 329 (it says 313 of 476 along the bottom of the page though). The configuration is in the standardjboss.xml file in the conf directory.

              I have tried each of the commit options and non of them help my application to work. I have also played with the transaction configuration setting in the ejb-jar.xml file. I tried no configuration, Required and NotSupported.

              I tried the exact same thing in JBoss-3.0.0 & it works fine with any Transaction setting (well I tried A & C and they both work).

              I moved to 3.0.2 because I was trying to find a fix to another similar problem where I get a Collection from a search. When I call next on the iterator & typecast the result back to the EJBLocalObject that I have; then I get a null pointer exception. This has been a problem for every version of JBoss I tried. I used Java reflection to find out what I could about what was going on - and it just got me more confused because it looks like it should work?!?! The code snippet looks like:


              Collection cEjbNum = ejbNumHome.findByUniqueId(id);
              System.err.println("Size matters: " + cEjbNum.size());
              UserDetailsNum ejbNum = (UserDetailsNum)cEjbNum.iterator().next();

              Class [] myInterfaces = ejbNum.getClass().getInterfaces();
              System.err.println("Size: " + myInterfaces.length);
              for(int index=0; index<myInterfaces.length; index++) {
              System.err.println("class: " +
              myInterfaces[index].getName());
              }

              // Exception thrown on this line
              Long lKey = ejbNum.getI1();



              ====

              Results:

              Size matters: 2
              Interface size: 1
              class: com.me.app.cmp2.UserDetailsNum
              [org.jboss.ejb.plugins.cmp.jdbc.JDBCLoadEntityCommand.UserDetailsNumEJB] Executing SQL: SELECT contactnumberkey,rowkey, i1, s1, s2 FROM CONTACT_NUMBER_VAL WHERE (contactnumberkey=?) OR (contactnumberkey=?)
              Exception caught trying to find id in UserDetailsNum
              java.lang.NullPointerException

              ===

              I am less convinced that the first problem is actually in my code as it works on 3.0.0. As for the second - well I'll just keep tearing my hair out for now I guess.

              Any advice on solutions or time frames for a fix would be greatly appreciated. Thanks again also to cyates for giving me a new direction to look at.

              cheers,
              Adrian

              • 4. Re: [Jboss3.0.2] A CMR collection may only be used within th
                Dain Sundstrom Master

                The problem is the spec does not allow a RelationSet (the return value of the CMR get accessor) to be used outside of the trasaction in which it was materialized. This means that if you are running without a transaction you can get the set but never use it. To use the set you must have a wrapping transaction using either a Session bean or UserTransaction.

                > Transactions are set to Required and commit-option is
                > 'A'.

                This has nothing to do with commit options.

                > All of which worked perfectly on 3.0.0, but fails
                > with the IllegalStateException on 3.0.1 and 3.0.2.

                This is because 3.0.0 had a bug that allowed a RelationSet to be used outside of transaction in which it was materialized.

                • 5. Re: [Jboss3.0.2] A CMR collection may only be used within th
                  Dain Sundstrom Master

                  > I moved to 3.0.2 because I was trying to find a fix
                  > to another similar problem where I get a Collection
                  > from a search. When I call next on the iterator &
                  > typecast the result back to the EJBLocalObject that I
                  > have; then I get a null pointer exception. This has
                  > been a problem for every version of JBoss I tried. I
                  > used Java reflection to find out what I could about
                  > what was going on - and it just got me more confused
                  > because it looks like it should work?!?! The code
                  > snippet looks like:

                  This is a completely different problem. What is the exception you are getting on the server side? What is the stack trace of the NullPointerException?

                  • 6. Re: [Jboss3.0.2] A CMR collection may only be used within th
                    Adrian Hallam Newbie

                    Dain - your a champion! Thanks, it's now working.

                    I am going to add some more info for the newby's at my level who may read this thread. I added a transaction based on the documentation 'JBoss.3.0QuickStart.Draft3.pdf' page 56. However, read the whole chapter as it's invaluable if you don't yet understand Transactions fully. Even after adding the code, it still didn't work until I changed the following in the ejb.jar <assembly-descriptor> section...

                    <container-transaction>

                    <ejb-name>UserEJB</ejb-name>
                    <method-name>*</method-name>


                    <ejb-name>RolesEJB</ejb-name>
                    <method-name>*</method-name>

                    <trans-attribute>Required</trans-attribute>
                    </container-transaction>


                    The important part is Required. I still have lots of reading to do, but if you look at the diagrams in the documentation references above it makes sense.


                    I also added another problem in this thread (which is probably bad form so my appologies). Here's what it was:

                    I was getting a NullPointerException because, now this may suprise some, my returned value was null. I was doing a query to return my primary key (which is two fields). However, I cut corners and setup my table with one primary key field even though there is actually two fields that make up the primary key in the database. So the record I was looking at in my SQL window was different to the record I was getting the null pointer exception on. I saved myself 15 minutes by not writing the primary key class and lost around a day figuring out my problem. hrmmm... one day I'll learn...

                    cheers,
                    Adrian

                    • 7. Re: [Jboss3.0.2] A CMR collection may only be used within th
                      Andrew Bachelard Newbie

                      Yes thanks very much Dain.
                      I didn't understand that you couldn't have a transaction across 2 entity beans. I have now wrapped it up in a session bean it is humming along beautifully.
                      Andrew

                      • 8. Re: [Jboss3.0.2] A CMR collection may only be used within th
                        Leo Chan Newbie

                        I had a session been with a save method that wrapper all the logic of create the entity beans. The transaction attribute is set to required. However, when I call the save method from a Junit test client. I still have the same problem. Can anyone tell me why?

                        • 9. Re: [Jboss3.0.2] A CMR collection may only be used within th
                          Dain Sundstrom Master

                          Make sure you are accessing the Collection in the same transaction in which it was retrieved. If you are not sure, you are most likely running without any transaction. In that case either create a wrapping session bean or start a user transaction.

                          • 10. Re: [Jboss3.0.2] A CMR collection may only be used within th
                            Ignacio de Cordoba Novice

                            Hi there,
                            I am facing the problem discussed in this thread. I can solve the problem by not getting the Collection outside the Session EJB, but what can I do if I want, for example, to iterate through the collection in a JSP Page?
                            I make intense use of the JSTL forEach Tag, as I was used to it when I used Pramati Server.
                            Now that I am migrating to JBoss, i get this error often...
                            I've read that I can wrap the Collection in a Transaction... can anyone please post an example of how to do this?

                            thanks a lot!!!

                            • 11. Re: [Jboss3.0.2] A CMR collection may only be used within th
                              Ignacio de Cordoba Novice

                              When I say wrap the Collection in a Transaction, I mean, start a Transaction...

                              • 12. Re: [Jboss3.0.2] A CMR collection may only be used within th
                                Brian Taylor Newbie

                                Is it in the CMP 2.0 spec that says that a CMR collection must be created within a Transaction and not used across transactions or is this JBoss specific? Doesn't this create quite a limitation on performance? I need to keep the transaction length very short. I'm currently iterating through a Collection of 2 million plus beans and need to support upwards of 10 million. Any help would be greatly appreciated.

                                • 13. Re: [Jboss3.0.2] A CMR collection may only be used within th
                                  Weiqing Huang Newbie

                                  > Is it in the CMP 2.0 spec that says that a CMR
                                  > collection must be created within a Transaction and
                                  > not used across transactions or is this JBoss
                                  > specific? Doesn't this create quite a limitation on
                                  > performance? I need to keep the transaction length
                                  > very short. I'm currently iterating through a
                                  > Collection of 2 million plus beans and need to
                                  > support upwards of 10 million. Any help would be
                                  > greatly appreciated.


                                  the requirement is defined in ejb spec section 10.4.2 and 10.3.8. it is not jobss-specific.

                                  in your case, perhaps you can use ejb-ql to select only values you are interested in, instead of the bean object itself. besides, it rarely makes sense to iterate 10 million objects. some kind of paging mechanism is needed. just my 2 cents.

                                  • 14. Re: [Jboss3.0.2] A CMR collection may only be used within th
                                    Tim Paulson Newbie

                                    I have discovered a satisfactory answer to the problem of CMR-based transaction errors in JSPs/Servlets.
                                    I embedded a little bit of Java code into my JSP page to surround the CMR-based accesses with a transaction. I found out how to implement a transaction from a JBoss client in the QuickStart guide. Here is the relevant part of my JSP page:

                                    <%@ page import="javax.naming.*,javax.transaction.UserTransaction" %>


                                    IdDescriptionCost
                                    <%
                                    Context jndiContext = new InitialContext();
                                    UserTransaction ut = (UserTransaction)jndiContext.lookup("UserTransaction");
                                    ut.begin();
                                    %>
                                    <c:forEach var="buy" items="${indiv.buys}">

                                    <c:out value="${buy.buyId}"/>
                                    <c:out value="${buy.description}"/>
                                    <c:out value="${buy.cost}"/>

                                    </c:forEach>
                                    <%
                                    ut.commit();
                                    %>


                                    In this case, I am using JSTL tags to control the loop and to access each of the "Buy" EJBs that are returned by the JSTL-based expression "${indiv.buys}". This expression is mapped to a EJB CMR accessor call (indiv.getBuys()).

                                    So, at the moment I have some messy looking Java code that surrounds the CMR-based stuff with a transaction. But, this can easily be converted into a special tag in my own tag library. I plan to implement a tag like:

                                    <mine:user_transaction>
                                    <!-- CMR accesses -->
                                    </mine:user_transaction>

                                    Information about Transactions in JBoss can be found in the QuickStart guide.

                                    I think it would be good to add some CMR-based accesses to CrimePortalTest.java of the "JBoss 3.0 Template" code (http://prdownloads.sourceforge.net/jboss/JBoss.3.0TemplateAndExamples.zip).