10 Replies Latest reply on Nov 2, 2011 10:08 AM by csa

    Errai RPC calls with JPA's Extended Persistence Context?

    superfis

      I'm using Errai RPC fo server calls. On server-side there are RPC services which are CDI beans. Database operations are being managed by Hibernate.

       

      My question is how to use Extended Persistence Context in scenatio described below, because currently I have an issue like this:

       

      ...

      org.hibernate.PersistentObjectException: detached entity passed to persist: com.mycomp.proj.shared.domain.Group: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mycomp.proj.shared.domain.Group

      ...

       

       

      The use case is creating a new user being assigned to groups - details in steps:


      1. On client side there is calling (by Errai RPC) remote service usersRPCService.saveNewUser(...)

      2. The service calls two additional CDI beans' methods - first for finding Group entities by theirs IDs, and second to save new User with assigned groups.

       

      Here a code snippets:

       

      UsersRPCService

       

      @Service

      @ApplicationScoped

      public class UsersRPCServiceImpl implements UsersRPCService {

       

       

        @Inject private UserTransaction utx;

                @Inject private UserService userService;

        @Inject private GroupService groupService;

       

       

          @Override

          public void saveNewUser( NewEditUserDTO newUserDto ) {

              User user = new User( );

              user.set... // here filling all user's properties on base of newUserDto content

              try {

                  utx.begin( );

                  List<Group> groups = groupService.getGroupsByIds( newUserDto.getGroupsIds( ) );

                  user.setGroups( groups );

                  userService.saveNewUser( user ); // here

      org.hibernate.PersistentObjectException: detached entity passed to persist

                  utx.commit( );

              }

              catch ( Exception e ) {}

          }

      }

       

       

      GroupService

       

      @ApplicationScoped

      @Transactional( TransactionPropagation.SUPPORTS )

      public class GroupService {

       

        @Inject Session session;

       

                public List<Group> getGroupsByIds( List<Long> ids ) {

              return session.createQuery( "select g from Group g where g.id in :ids" ).setParameterList( "ids", ids ).list( );

          }

      }

       

       

      UserService


      @ApplicationScoped

      @Transactional( TransactionPropagation.SUPPORTS )

      public class UserService {

       

       

          @Inject Session session;

       

          public User saveNewUser( User user ) throws Exception {

              session.save( user );

              session.flush( );

              return user;

          }

      }

       

      and Hibernate's Session producer

       

      @ApplicationScoped

      public class HibernateSessionProducer {

       

          @PersistenceContext( type = PersistenceContextType.EXTENDED )

          private EntityManager em;

       

          @Produces

          public Session getHibernateSession( ) {

              return ( Session ) em.getDelegate( );

          }

      }

       

      It looks like in groupService and userService there are used different sessions and group entities comming from groupService are just detached when assigning to user in usersRPCService.saveNewUser(...).

       

      I understand that it happens because of server-side Errai RPC calls implementation - beans are handled out of container's CDI context.

       

      I will be thankful for any advise about how to modify my code to have Extended Persistence Context active.

        • 1. Re: Errai RPC calls with JPA's Extended Persistence Context?
          csa

          Hi Slawomir,

           

          I can look into this.

           

          Two immediate thoughts: Have you tried using session.merge(user) in your UserService.saveNewUser method to attach the entity? Also I'd probably create the instance of the User and set its properties after utx.begin().

           

          In general, this should work as your RPC Service is also @ApplicationScoped.

           

          Cheers,

          Christian

          • 2. Re: Errai RPC calls with JPA's Extended Persistence Context?
            superfis

            Hi Christian,

             

            session.merge(user) is working but that's not solving my problem in general - it's only a kind of workaround (and hitting too much the database unnecessarily in this case).

             

            Creating new instance of User class in transaction (after utx.begin()) doesn't solve the issue unfortunately

            • 3. Re: Errai RPC calls with JPA's Extended Persistence Context?
              csa

              I am assuming you have tried marking your RPC service as @Transactional (btw, which container are you using)?

               

              Another immediate workaround (without calling session.merge) would be to create a new @Transactional service that takes your DTO and then uses your Group and UserService. Your RPC endpoint would then just call this new service.

              • 4. Re: Errai RPC calls with JPA's Extended Persistence Context?
                superfis

                I solved my problem using JPA's EntityManager instead of Hibernate's Session. EntityManager supports Entended Persistence Context while Session not. It may be because of my HibernateSessionProducer implementation...

                 

                I prefer Hibernate's Session over EntityManager due to many usefull extension, but I noticed that to use e.g. filters I han do it like this:

                 

                Session session = ( Session ) em.getDelegate( );

                session.setFilter( );

                 

                em.createQuery( ... ).getResultList( );

                • 5. Re: Errai RPC calls with JPA's Extended Persistence Context?
                  superfis

                  btw, I'm using jboss as 7.0.2. 

                  • 6. Re: Errai RPC calls with JPA's Extended Persistence Context?
                    csa

                    I am glad you got it working now. However, if I understand this correctly your getGroupIds and saveNewUser methods are running in separate transactions, which is why you need the Extended Persistence context for your group entities to stay attached. Ideally, this shouldn't be necessary and a single transaction should suffice.

                     

                    I have created a JIRA to look into supporting @Transactional methods on ErraiCDI/RPC endpoints: https://issues.jboss.org/browse/ERRAI-160

                    • 7. Re: Errai RPC calls with JPA's Extended Persistence Context?
                      superfis

                      Interesting... I switched from

                       

                      @PersistenceContext( type = PersistenceContextType.EXTENDED )

                          private EntityManager em;

                       

                      to

                       

                      @PersistenceContext

                          private EntityManager em;

                       

                      in UserService and GroupService and the effect remains the same - I have it still working correctly. Do I have 2 different transactions there?

                      I'm a bit confusead...

                      • 8. Re: Errai RPC calls with JPA's Extended Persistence Context?
                        csa

                        Are you using @Transactional on your RPC endpoint now or still a UserTransaction? Can you confirm that it works in both cases using the standard persistence context? If so, it seems we don't have a problem to fix. As mentioned above, you should not need an extended persistence context in this case because it really should take only one transaction.

                        • 9. Re: Errai RPC calls with JPA's Extended Persistence Context?
                          superfis

                          When I use @Transactional, I receive

                           

                          javax.persistence.TransactionRequiredException: Transaction is required to perform this operation (either use a transaction or extended persistence context)

                           

                          so, it looks like the is a need to manage transactions manually for now.

                           

                           

                          Concerning using @PersistenceContext vs @PersistenceContext(EXTENDED) - both are working, so It looks like default persistence context is enough (all activities are in one transaction).

                          • 10. Re: Errai RPC calls with JPA's Extended Persistence Context?
                            csa

                            OK, thanks! We will look into supporting @Transactional.