fix(manager-api): `@Transactional` interceptor edge case to emulate existing Apiman behaviour
MODIFY
manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/interceptors/BlobResourceInterceptorProvider.java
manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/interceptors/BlobResourceInterceptorProvider.java
@@ -18,6 +18,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.transaction.Transactional;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.UriBuilder;
@@ -58,8 +61,14 @@ import static org.apache.commons.lang3.reflect.FieldUtils.getAllFields;
public class BlobResourceInterceptorProvider implements WriterInterceptor {
private static final IApimanLogger LOGGER = ApimanLoggerFactory.getLogger(BlobResourceInterceptorProvider.class);
+ // @Inject EntityManagerFactoryAccessor emf;
- public BlobResourceInterceptorProvider() {}
+ public BlobResourceInterceptorProvider() {
+ }
+
+ // private EntityManager getEm() {
+ // emf.createEntityManager();
+ // }
/**
* {@inheritDoc}
@@ -67,7 +76,15 @@ public class BlobResourceInterceptorProvider implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
try {
+ // boolean startedOwnTx = false;
+ // if (!getEm().getTransaction().isActive()) {
+ // getEm().getTransaction().begin();
+ // startedOwnTx = true;
+ // }
rewrite(context);
+ // if (startedOwnTx) {
+ // getEm().getTransaction().commit();
+ // }
context.proceed();
} catch (IllegalAccessException e) {
throw new IOException(e);

MODIFY
manager/api/war/tomcat8/src/main/java/io/apiman/manager/api/war/tomcat8/ApimanTransactionalInterceptor.java
manager/api/war/tomcat8/src/main/java/io/apiman/manager/api/war/tomcat8/ApimanTransactionalInterceptor.java
@@ -2,6 +2,7 @@ package io.apiman.manager.api.war.tomcat8;
import io.apiman.manager.api.core.exceptions.StorageException;
import io.apiman.manager.api.jpa.EntityManagerFactoryAccessor;
+import io.apiman.manager.api.rest.exceptions.AbstractRestException;
import io.apiman.manager.api.rest.exceptions.SystemErrorException;
import io.apiman.manager.api.rest.impl.util.DataAccessUtilMixin;
@@ -24,24 +25,25 @@ public class ApimanTransactionalInterceptor implements DataAccessUtilMixin {
@Inject
EntityManagerFactoryAccessor emf;
- private EntityManager em;
public ApimanTransactionalInterceptor() {
- System.err.println("Apiman transactional interceptor is running");
+ }
+
+ private EntityManager getEm() {
+ return emf.getEntityManager();
}
@AroundInvoke
public Object intercept(InvocationContext ic) throws Exception {
- em = emf.getEntityManager();
- if (!em.getTransaction().isActive()) {
+ if (!getEm().getTransaction().isActive()) {
return invokeInOurTx(ic);
} else {
- return invokeInCallerTx(ic, em.getTransaction());
+ return invokeInCallerTx(ic, getEm().getTransaction());
}
}
private Object invokeInOurTx(InvocationContext ic) throws Exception {
- EntityTransaction tx = em.getTransaction();
+ EntityTransaction tx = getEm().getTransaction();
tx.begin();
try {
return ic.proceed();
@@ -56,10 +58,14 @@ public class ApimanTransactionalInterceptor implements DataAccessUtilMixin {
private void endTransaction(EntityTransaction tx) throws Exception {
try {
if (!tx.getRollbackOnly()) {
- if (tx.isActive()) {
+ if (getEm().isOpen() && tx.isActive()) {
+ try {
tx.commit();
- } else {
- System.err.println("Someone else closed the TX?");
+ } catch (AbstractRestException e) { // Emulates the way Apiman handled commit exceptions in earlier versions
+ throw e;
+ } catch (Throwable e) {
+ throw new SystemErrorException(e);
+ }
}
} else {
tx.rollback();
@@ -67,7 +73,9 @@ public class ApimanTransactionalInterceptor implements DataAccessUtilMixin {
} catch (Exception e) {
handleException(e, tx);
} finally {
- em.close();
+ if (getEm().isOpen()) {
+ getEm().close();
+ }
}
}

fix(manager-api): `@Transactional` interceptor edge case to emulate existing Apiman behaviour