6 Replies Latest reply on Sep 19, 2007 10:06 AM by Fernando Montaño

    org.hibernate.exception.GenericJDBCException: Cannot open co

    Robin Newbie

      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
          Miloslav Vlach Novice

          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 Novice

            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
              Alex Ka Novice

              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 Montaño Expert

                 

                "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
                  Alex Ka Novice

                  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 Montaño Expert

                    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);
                     }
                     }