0

I have set up a very simple Java web project (using NetBeans' Web Application template). It is deployed on Payara 6.2025.7 with a H2 database as a JTA data source.

I can't get EntityExistsException from persisting the same Entity twice. Instead, I always get jakarta.persistence.PersistenceException. Nested are internal exceptions with details what constraint has been violated.

Here is the code I am using:

@GET
@Path("throwme")
@Transactional
public Response exceptional(){
  E e = new E();
  e.setId("yolo");
  em.persist(e);
  return Response
    .ok("you can't see me twice!")
    .build();
}

just in case it would make any difference, here is the definition of entity E:

@Entity
@Data
public class E {
    @Id
    @GeneratedValue
    private String id;
    
    private int desyncer;
}

(@Data is from lombok)

The expected behavior is that I should get EnityExistsException after second request of \throwme resource. Instead, I get this:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 4.0.1.payara-p4.v202504221851): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_45 ON PUBLIC.E(ID) VALUES ( /* 25 */ 'yolo' )"; SQL statement:

It seems my problem is similar to the issue: https://github.com/eclipse-ee4j/eclipselink/issues/2170 but I can't reproduce the solution mentioned in the last post.

UPDATE: While trying to get to the root cause of the problem I have modified the code so it looks like this:

@GET
    @Path("throwme")
    @Transactional
    public Response exceptional(){
        try{
        E e = new E();
        e.setId("yolo");
        em.persist(e);
        em.flush();
        }catch(Exception e){
            System.out.println(e.getClass());
        }
        return Response
                .ok("you can't see me!")
                .build();
    }

Now I am convinced that the root exception is jakarta.persistence.PersistenceException and it is thrown at em.flush()

9
  • Don´t use @Data - > use @Getter or @Setter Commented Jul 21 at 12:11
  • @Raw any reasons why? @Data provides equals() and hashCode() Commented Jul 21 at 13:32
  • 1
    You can see it here stackoverflow.com/questions/75181366/… Or for more information medium.com/@jonas.friedli/… Commented Jul 22 at 7:17
  • This looks like EclipseLink logging. Are you sure your application is getting a DatabaseException from the persist or the transaction commit call and not a PersistenceException wrapping that DatabaseException? Commented Jul 22 at 14:58
  • 1
    The why answer is that the specification details flush (and transaction commit) result in the generic PersistenceException. EclipseLink has its own DatabaseException that would wrap the actual exception, and rather than do extra processing to determine the cause again from the many other potential errors during synchronization to the DB, just wrapped them all generically. Commented Jul 24 at 18:38

1 Answer 1

0

EclipseLink logging wraps Database exceptions in a org.eclipse.persistence.exceptions.DatabaseException which is what it passes through it's native stack, and what will get logged with its logging, and is what is being logged in the snip you posted.

The JPA specification details that flush (and transaction commit) result in the generic PersistenceException. EclipseLink rather than do extra processing to determine the cause again from the many other potential errors during synchronization to the DB, just wrapped them all generically. So in this case you'll get a PersistenceException wrapping its native DatabaseException detailing the cause.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.