6 Replies Latest reply on Sep 19, 2007 10:06 AM by fernando_jmt

    org.hibernate.exception.GenericJDBCException: Cannot open co

    robin.hultman

      I have a SFSB with this factory:

      @Factory("userSubscriptions")
       public void getUserSubscriptions() {
       userSubscriptions = em.createQuery("FROM Subscription s WHERE s.user.sign=:sign ORDER BY s.prio")
       .setParameter("sign", getCurrentUser().getSign())
       .getResultList();
       }


      This collection is used as value for a datatable and works fine. When I click a button in which triggers an action in which userSubscriptions is accessed again I get:

      2007-08-30 09:22:49,843 INFO [org.hibernate.event.def.DefaultLoadEventListener] Error performing load command
      org.hibernate.exception.GenericJDBCException: Cannot open connection
      Caused by: org.jboss.util.NestedSQLException: Transaction is not active:


      To me "Cannot open connection" indicates some problem with the database but thats not possible since I do a lot of other db operations.

      I think I can get around this problem by doing the transactions manually but do I really want to do that? I've had a lot of problems with this in my application so any tips would be most appreciated =).

        • 1. Re: org.hibernate.exception.GenericJDBCException: Cannot ope
          mvlach

          Hi, I have the same problem you are wrote. Some of DB operations succesed but some throws this exception.

          • 2. Re: org.hibernate.exception.GenericJDBCException: Cannot ope
            stephen.friedrich

            Typically this means there was a previous error that corrupted the transaction.

            Specifically I have been getting this when trying to use MyFaces Trinidad with Sun's JSF RI. For some strange reason whenever a validation fails from that point on you'll get this error.

            • 3. Re: org.hibernate.exception.GenericJDBCException: Cannot ope
              wise_guybg

              I'm facing the same problem but with another idea in my mind:
              http://www.jboss.com/index.html?module=bb&op=viewtopic&t=118991

              I have been dealing with a similar problem in a previous project at work where we used Hibernate. The solution was to create a backing session that will help you recover gracefully in case of DBException/ContraintViolation.

              I was wondering if something similar can/should be done in Seam/EJB3.

              • 4. Re: org.hibernate.exception.GenericJDBCException: Cannot ope
                fernando_jmt

                 

                "wise_guybg" wrote:

                I have been dealing with a similar problem in a previous project at work where we used Hibernate. The solution was to create a backing session that will help you recover gracefully in case of DBException/ContraintViolation.

                I was wondering if something similar can/should be done in Seam/EJB3.


                Sure, you can.

                My experience as code (a simple example):

                ACTION:
                @Name("userAction")
                @Scope(ScopeType.CONVERSATION)
                public class UserAction {
                
                 @In(required = false)
                 @Out(required = false)
                 private User user;
                
                 @In(create = true)
                 protected UserService userService;
                
                 @End
                 public String create() {
                 try {
                
                 userService.create(user);
                 addCreatedMessage();
                 return Outcome.SUCCESS;
                 } catch (EntryDuplicatedException e) {
                 addDuplicatedMessage();
                 return null;
                 }
                 }
                }
                


                SERVICE:
                
                @Stateful
                @Name("userService")
                @Scope(CONVERSATION)
                public class UserServiceBean implements UserService {
                
                
                 @In(value="#{entityManager}")
                 private EntityManager em;
                
                
                 public void create(User entity) throws EntryDuplicatedException {
                 try {
                 em.persist(entity);
                 em.flush();
                 } catch (EntityExistsException e) {
                 throw new EntryDuplicatedException();
                 }
                 }
                
                }
                


                • 5. More code needed
                  wise_guybg

                  Is there something special about EntryDuplicatedException?

                  Also, what is your experience with addDuplicatedMessage()? Does this methog try to access the database in any way?

                  Example of a problem:

                  Let's say UserAction has a method

                  @End
                  public String save()


                  The UserService tries to merge the user entity bean but an exception occurs (i.e. UniqueConstraint on the First+Last Name). This means that the changes to the object are invalid. In my experience if you try to use the entity manager in the catch clause you will receive a "Transaction not active" error. Then how could I reload the object and return to its persisted state?

                  • 6. Re: org.hibernate.exception.GenericJDBCException: Cannot ope
                    fernando_jmt

                    EntryDuplicatedException is a custome exception I have:

                    
                    @ApplicationException(rollback = true)
                    public class EntryDuplicatedException extends Exception {
                    
                     public EntryDuplicatedException() {
                     }
                    
                    }
                    


                    addDuplicatedMessage() is just a simple method to add the error message to the view (FacesMessages..)

                    Finally, you should use @TransactionAttribute(REQUIRES_NEW) for the especific method you want to recover after the transaction fails:

                    @TransactionAttribute(REQUIRES_NEW)
                     public void update(User entity) throws ConcurrencyException, EntryDuplicatedException {
                     try {
                     em.merge(entity);
                     em.flush();
                     } catch (EntityExistsException ee) {
                     throw new EntryDuplicatedException(ee);
                     }
                     }