Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unable to catch hibernate exception caused by constraints violation

I have looked through the many other questions on not catching exceptions ( including Can't catch ConstraintViolationException ) but none are covering the same issue as me.

using RestEasy to network and Hibernate to link with Postgres db.

I have an object:

@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"user_id"})})
public class Outcome {

    @Id
    @GeneratedValue
    private Long id;

    @OneToOne
    private User user;

    private String anotherAttribute;
}

The db service is sent an Outcome via OutcomeResource.saveOutcome:

@POST
@Consumes("application/json")
@Transactional
public Response saveOutcome(Outcome outcome){
    try {
        myRepository.save(outcome);
        return Response.ok().build();
    } catch (Exception e) {
        System.out.println("I caught the exception:" + e);
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
}

which is then persisted in the db by OutcomeRepository.save:

public void save(Outcome outcome) {
    try {
        getEntityManager().persist(outcome);
    } catch (Exception e) {
        System.out.println("No I caught the exception : " + e);
    }
}

when the first Outcome is posted and saved for a user it is sucessfully saved in the db. If a second outcome is posted an error is thrown as would be expected.

A shortened error stack trace is:

javax.persistence.RollbackException: 
   Error while committing the transaction
   Description: The server encountered an unexpected condition that
   prevented it from fulfilling the request.
   Exception: org.jboss.resteasy.spi.UnhandledException:
   javax.persistence.RollbackException: Error while committing the transaction
org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:78)...
Root cause: javax.persistence.RollbackException: 
    Error while committing the transaction...
Root cause: javax.persistence.PersistenceException:
    org.hibernate.exception.ConstraintViolationException: 
    could not execute statement...
Root cause: org.hibernate.exception.ConstraintViolationException: 
    could not execute statement...
Root cause: postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint
    Detail: Key (user_id)=(361) already exists.

I would like to catch this error to return a bad request response. Despite trying to catch the generic Exception and each specific type of exception in the stack trace, neither catch block is entered.

Why is neither method catching the exception and how is it possible to do so?

like image 928
D.Rees Avatar asked Sep 15 '25 00:09

D.Rees


1 Answers

Hours of researching later i have found out..

It is not possible to catch the exception because it is being thrown after the methods complete. This is because the service layer method is marked as @Transactional so hibernate will not throw the exception until that transaction has ended.

If using spring: Writing a after-throwing advice which converts the exception will apparently allow you to handle this, however I have not tested this.

I have not found a way to handle this exception in Guice so will be leaving it unhandled. This is OK in my situation.

good source of information: http://forum.spring.io/forum/spring-projects/data/68995-transaction-manager-appears-to-be-eating-the-runtime-exception

like image 81
D.Rees Avatar answered Sep 17 '25 02:09

D.Rees