13 Replies Latest reply on Jul 21, 2006 8:16 PM by David Bernstein

    how to configure a session bean managing entity beans with @

    David Bernstein Newbie

      I would like to have a web page where a user can manage "groups" that he or she belongs to. There are entity beans for users and groups, which have a @ManyToMany relationship (where I've set the user as the owning side). The MessageManagerBean class in the examples seemed very similar to what I need, so I started with that and made a "groupManager" stateful session bean; the user is injected from having logged in and the @DataModel is a list of the groups that the user belongs to. The user entity bean has a collection of groups and the group entity bean has a collection of users, with appropriate EJB3 annotations. When I try to bring up the group management page that references the group manager bean, I get:

      org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.orgmob.member.User.groups, no session or session was closed
      


      I looked at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=85894&start=0, which seems to suggest using eager fetching for this, but since there's a many-to-many relationship, I'd have the risk of pulling the entire user and group tables into memory, wouldn't I?

      What's the right approach for this? Thanks in advance and apologies if I've missed previously posted discussion or documentation or am misunderstanding eager fetching.

        • 1. Re: how to configure a session bean managing entity beans wi
          David Bernstein Newbie

          title truncated: should have ended: ...@ManyToMany

          • 2. Re: how to configure a session bean managing entity beans wi
            Gavin King Master

            Don't use the session-scoped user for updating admin data. Load a different User instance into the conversation scope.

            • 3. Re: how to configure a session bean managing entity beans wi
              David Bernstein Newbie

              Thanks for the prompt response, Gavin. I'll try something with the @Role annotation as suggested by the "Components with multiple roles" section of the reference. It's late enough here that I think I'll try tomorrow morning so as not to inflict unintended damage. :-) [semi-non-sequitur:] I am still stumped with suggestion to use page actions for stopping unlogged-in users from seeing pages, since it gave me an infinite server/browser redirect loop (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=87118)...

              • 4. Re: how to configure a session bean managing entity beans wi
                David Bernstein Newbie

                I tried to follow all the instructions in the reference, but using the bean (see GroupManagerBean.create) causes a rollback/synchronization problem (which see at bottom of post)

                I wouldn't be surprised if there were issues in how the @Role stuff was done, but I couldn't find a single example of its usage anywhere in real code. I also hope I configured the managed persistence context right.

                Files and error:

                User.java

                ...
                @Entity
                @Name("user")
                // default scope is CONVERSATION
                @Role(name="currentUser", scope=SESSION)
                @Table(name="USERS")
                public class User implements Serializable {
                 ...
                 private Set<Group> groups = new HashSet<Group>();
                
                 @ManyToMany
                 @JoinTable(name="USER_GROUP",
                 joinColumns={@JoinColumn(name="USER_ID")},
                 inverseJoinColumns={@JoinColumn(name="GROUP_ID")})
                 public Set<Group> getGroups() {
                 return groups;
                 }
                 public void setGroups( Set<Group> groups ) {
                 this.groups = groups;
                 }
                }
                


                Group.java

                @Entity
                @Name("group")
                // default scope is CONVERSATION
                @Table(name="GROUPS")
                public class Group implements Serializable {
                 ...
                 private Set<User> users = new HashSet<User>();
                
                 @ManyToMany(mappedBy="groups")
                 public Set<User> getUsers() {
                 return users;
                 }
                 public void setUsers( Set<User> users ) {
                 this.users = users;
                 }
                }
                


                GroupManagerBean.java

                @Stateful
                @Name("groupManager")
                // default scope is CONVERSATION
                @LoggedIn
                public class GroupManagerBean implements GroupManager, Serializable {
                 ...
                 @DataModel
                 private List<Group> groupList;
                
                 @DataModelSelection
                 @Out(required=false)
                 private Group group;
                
                 @In
                 private User user;
                
                 @PersistenceContext(type=EXTENDED)
                 private EntityManager orgmobDatabase;
                
                 @Factory("groupList")
                 public void find() {
                 groupList = new ArrayList<Group>( user.getGroups() );
                 }
                
                 public void create() {
                 group = new Group();
                 group.setGroupname( newGroupname() );
                 user.getGroups().add( group );
                 }
                }
                


                LoginAction.java

                @Stateless
                @Name("login")
                public class LoginAction implements Login {
                
                 @In @Out
                 private User currentUser;
                
                 // COMMENTING OUT user JUST MOVES THE ROLLBACK/SYNCHRONIZATION
                 // PROBLEM TO OCCUR IN THE GROUP MANAGER
                 @Out
                 private User user;
                
                 @PersistenceContext
                 private EntityManager orgmobDatabase;
                
                 public String login() {
                 List<User> results = orgmobDatabase.createQuery(
                 "from User where username=:username and password=:password")
                 .setParameter("username", currentUser.getUsername())
                 .setParameter("password", currentUser.getPassword())
                 .getResultList();
                 String action;
                 if ( results.size()==0 ) {
                 FacesMessages.instance().add("#{messages.errorInvalidLogin}");
                 action = "login";
                 }
                 else {
                 // IS THIS HOW YOU USE COMPONENT WITH MULTIPLE ROLES?
                 // THERE ARE NO EXAMPLES OF @Role USAGE.
                 user = currentUser = results.get(0);
                
                 Contexts.getSessionContext().set(LOGGED_IN, true);
                 FacesMessages.instance().add("#{messages.infoWelcome}");
                 action = "groups";
                 }
                 return action;
                
                 }
                }
                


                faces-config.xml

                <?xml version="1.0" encoding="UTF-8"?>
                <!DOCTYPE faces-config
                PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
                 "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
                <faces-config>
                
                 <!-- Navigation rules for the app -->
                 <navigation-rule>
                 ...
                 </navigation-rule>
                
                 <!-- Facelets support -->
                 <application>
                 <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
                
                 <!-- ??? -->
                 <navigation-handler>org.jboss.seam.jsf.SeamNavigationHandler</navigation-handler>
                 <state-manager>org.jboss.seam.jsf.SeamStateManager</state-manager>
                 <variable-resolver>org.jboss.seam.jsf.SeamVariableResolver</variable-resolver>
                
                 </application>
                
                
                 <!-- Phase listener needed for all Seam applications -->
                
                 <lifecycle>
                 <!-- phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener -->
                 <phase-listener>
                 org.jboss.seam.jsf.SeamExtendedManagedPersistencePhaseListener
                 </phase-listener>
                 </lifecycle>
                
                </faces-config>
                


                components.xml

                <components>
                
                 <component name="org.jboss.seam.core.init">
                 <property name="myFacesLifecycleBug">true</property>
                 <property name="jndiPattern">member/#{ejbName}/local</property>
                 </component>
                
                 <component class="org.jboss.seam.core.Ejb"
                 installed="false"/>
                
                
                 <!-- Configuring a managed persistence context -->
                 <component name="orgmobDatabase"
                 class="org.jboss.seam.core.ManagedPersistenceContext">
                 <property name="persistenceUnitJndiName">java:/EntityManagerFactories/orgmobData</property>
                 </component>
                
                </components>
                


                persistence.xml

                <persistence>
                 <persistence-unit name="orgmobDB">
                 <provider>org.hibernate.ejb.HibernatePersistence</provider>
                 <jta-data-source>java:/DefaultDS</jta-data-source>
                 <properties>
                 <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
                 <property name="jboss.entity.manager.factory.jndi.name"
                 value="java:/EntityManagerFactories/orgmobData" />
                 </properties>
                 </persistence-unit>
                </persistence>
                


                rollback/synchronization exception:


                2006-07-20 14:54:06,226 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/member].[Faces Servlet]] Servlet.service() for servlet Faces Servlet threw exception
                javax.faces.el.EvaluationException: Exception while invoking expression #{groupManager.create}
                at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:153)
                at org.jboss.seam.core.Pages.callAction(Pages.java:212)
                at org.jboss.seam.jsf.AbstractSeamPhaseListener.callPageActions(AbstractSeamPhaseListener.java:127)
                at org.jboss.seam.jsf.AbstractSeamPhaseListener.beforeRender(AbstractSeamPhaseListener.java:98)
                at org.jboss.seam.jsf.SeamPhaseListener.beforePhase(SeamPhaseListener.java:50)
                at org.jboss.seam.jsf.SeamExtendedManagedPersistencePhaseListener.beforePhase(SeamExtendedManagedPersistencePhaseListener.java:38)
                at org.apache.myfaces.lifecycle.LifecycleImpl.informPhaseListenersBefore(LifecycleImpl.java:520)
                at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:342)
                at javax.faces.webapp.FacesServlet.service(FacesServlet.java:107)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                at org.jboss.seam.servlet.SeamRedirectFilter.doFilter(SeamRedirectFilter.java:30)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
                at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
                at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
                at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
                at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
                at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
                at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
                at java.lang.Thread.run(Thread.java:595)
                Caused by: java.lang.RuntimeException: org.hibernate.TransactionException: Could not register synchronization
                at org.jboss.ejb3.stateful.StatefulBeanContext.remove(StatefulBeanContext.java:273)
                at org.jboss.ejb3.AbstractPool.remove(AbstractPool.java:171)
                at org.jboss.ejb3.cache.simple.SimpleStatefulCache.remove(SimpleStatefulCache.java:299)
                at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:89)
                at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78)
                at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
                at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
                at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                at org.jboss.ejb3.stateful.StatefulContainer.localInvoke(StatefulContainer.java:188)
                at org.jboss.ejb3.stateful.StatefulLocalProxy.invoke(StatefulLocalProxy.java:98)
                at $Proxy850.create(Unknown Source)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:585)
                at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:129)
                ... 29 more
                Caused by: org.hibernate.TransactionException: Could not register synchronization
                at org.hibernate.transaction.CMTTransaction.registerSynchronization(CMTTransaction.java:159)
                at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:59)
                at org.jboss.ejb3.stateful.StatefulBeanContext.closeExtendedPCs(StatefulBeanContext.java:284)
                at org.jboss.ejb3.stateful.StatefulBeanContext.remove(StatefulBeanContext.java:268)
                ... 47 more
                Caused by: javax.transaction.RollbackException: Already marked for rollback TransactionImpl:XidImpl[FormatId=257, GlobalId=diamond/9567, BranchQual=, localId=9567]
                at org.jboss.tm.TransactionImpl.registerSynchronization(TransactionImpl.java:635)
                at org.hibernate.transaction.CMTTransaction.registerSynchronization(CMTTransaction.java:156)
                ... 50 more



                Putting the user variable into LoginAction moves the rollback/synchronization problem there. Commenting it out delays the problem to usage of the group manager bean.


                • 5. Re: how to configure a session bean managing entity beans wi
                  Gavin King Master

                  Step through your code. The error you see is hiding the real error (this is due to a fixed bug in EJB3)

                  • 6. Re: how to configure a session bean managing entity beans wi
                    David Bernstein Newbie

                    I have already spent hours stepping through the code and thousands of lines of server logs and staring at the 147-page reference manual trying to make this work. If you already know my mistake, please kindly point it out rather than making this an exercise for the reader. The fact that the actual problem is obscured by an EJB3 implementation defect is no help and hardly encouraging in my choice to choose bleeding-edge technologies from JBoss while I try to create a product to feed myself.

                    • 7. Re: how to configure a session bean managing entity beans wi
                      David Bernstein Newbie

                      So, about a thousand lines up from the bottom, I see that the LIE remains. I've tried to follow the instructions but admit that I must not be seeing something. I thought I understood that changing the scopes to CONVERSATION, having the group bean manager use a conversation-scoped instance, and following the instructions for using special Seam managed persistence would fix the LIE problem, but apparently I'm mistaken in my understanding or implementation of those instructions. I will gratefully accept having the error of my ways pointed out to me.

                      Also, about the EJB3 bug, does that mean I need to get some patch in order to continue my work once the LIE problem is fixed?

                      • 8. Re: how to configure a session bean managing entity beans wi
                        Justin Newbie

                        Where do you @Begin and @End your conversation in GroupManagerBean?

                        • 9. Re: how to configure a session bean managing entity beans wi
                          Gavin King Master

                           

                          "dbatcn" wrote:
                          The fact that the actual problem is obscured by an EJB3 implementation defect is no help and hardly encouraging in my choice to choose bleeding-edge technologies from JBoss while I try to create a product to feed myself.


                          If you're not happy using new technologies, you have two clear choices:

                          (1) Don't use them
                          (2) Use them and don't complain about occasional hiccups

                          I think that's reasonable, don't you?



                          • 10. Re: how to configure a session bean managing entity beans wi
                            Gavin King Master

                             

                            If you already know my mistake, please kindly point it out rather than making this an exercise for the reader.


                            And P.S. I do not know what mistake you made. I tried to helpfully point out that the exception in the log is not the one you need to find, because you need to find the real one in order to discover the real cause of the problem.

                            • 11. Re: how to configure a session bean managing entity beans wi
                              David Bernstein Newbie

                              I found Justin's pointing out the lack of required annotations to be helpful and am following up on that.

                              • 12. Re: how to configure a session bean managing entity beans wi
                                David Bernstein Newbie

                                I apologize for any implication that information about a known mistake may have been withheld. Mea culpa.

                                • 13. Re: how to configure a session bean managing entity beans wi
                                  David Bernstein Newbie

                                  It seems to be running much better now. A word to the wise to people who might encounter the same problem: note that the manual says to change the annotation on your entity manager from @PersistenceContext to @In(create=true) when using Seam-managed transactions and don't forget to change them all, taking care that their names match. The magic of bijection takes a little getting used to. :-)

                                  Thank you to Gavin and Justin for their assistance.