Question

I have a field with an unique constraint:

@Column(unique=true)
private String uriTitle;

When I try to save two entities with the same value, I get an exception - but another exception than I exected:

java.lang.IllegalStateException: <|Exception Description: No transaction is currently active
        at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122)
        at com.example.persistence.TransactionFilter.doFilter(TransactionFilter.java:35)

The questionable filter method looks like this:

public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain)
          throws IOException, ServletException {
    EntityManager entityManager = ThreadLocalEntityManager.get();
    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    try {
      chain.doFilter(request, response);
      transaction.commit();
    }
    catch (Throwable t) {
      transaction.rollback();  // line 35, mentioned in the exception
      throw new RuntimeException(t);
    }
    finally {
      entityManager.close();
      ThreadLocalEntityManager.reset();
    }
}

... and the ThreadLocalEntityManager like this:

public class ThreadLocalEntityManager {

    private static EntityManagerFactory entityManagerFactory = null;
    private static final ThreadLocal<EntityManager> entityManager =
        new ThreadLocal<EntityManager>() {
            @Override 
            protected EntityManager initialValue() {
                return entityManagerFactory.createEntityManager();
            }
        };

    private ThreadLocalEntityManager() {}

    public static synchronized void init(String persistenceUnit) {
        requireNotNull(persistenceUnit);
        requireState(entityManagerFactory == null, "'init' can be called only "
                        + "once.");
        entityManagerFactory =
                        Persistence.createEntityManagerFactory(persistenceUnit);
    }

    public static EntityManager get() {
        requireState(entityManagerFactory != null, "Call 'init' before calling "
                        + "'get'");
        return entityManager.get();
    }

    public static void reset() {
        entityManager.remove();
    }

}

I wrapped the call to save with try ...catch to handle the unique constraint violation, but that doesn't work:

try {
    ThreadLocalEntityManager.get().persist(article); // article is constrained
}
catch(Throwable t) {
    t.printStackTrace();
}

Any idea why there is no transaction? What is the correct way to handle a unique constraint violation?

Was it helpful?

Solution

Your transaction rolled back automatically due to DB constraint violation, therefore there is no transaction to rollback manually. To handle this case, you can write

catch (Throwable t) {
  if (transaction.isActive()) 
    transaction.rollback();  // line 35, mentioned in the exception 
  throw new RuntimeException(t); 
}

OTHER TIPS

You don't have any separation between transactions and GUI in your application. You will have problems with transaction handling in general.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top