Merge branch 'develop' into stable
This commit is contained in:
commit
cfcb7fd75a
12
pom.xml
12
pom.xml
@ -75,6 +75,18 @@
|
||||
<version>1.0.1</version>
|
||||
<type>amp</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>javax.transaction-api</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
<artifactId>jakarta.transaction-api</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- AMP resources are included in the WAR, not the extension directory; this makes aspectjweaver available to javaagent -->
|
||||
<dependency>
|
||||
|
@ -1,113 +0,0 @@
|
||||
package com.inteligr8.alfresco.annotations;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public class TransactionalWrapper {
|
||||
|
||||
private Transactional stxl = null;
|
||||
private javax.transaction.Transactional jtxl = null;
|
||||
|
||||
public TransactionalWrapper(Transactional txl) {
|
||||
this.stxl = txl;
|
||||
}
|
||||
|
||||
public TransactionalWrapper(javax.transaction.Transactional txl) {
|
||||
this.jtxl = txl;
|
||||
}
|
||||
|
||||
public static TransactionalWrapper wrap(Method method) {
|
||||
Transactional stxl = method.getAnnotation(Transactional.class);
|
||||
javax.transaction.Transactional jtxl = method.getAnnotation(javax.transaction.Transactional.class);
|
||||
if (stxl == null && jtxl == null) {
|
||||
return null;
|
||||
} else if (stxl != null) {
|
||||
return new TransactionalWrapper(stxl);
|
||||
} else if (jtxl != null) {
|
||||
return new TransactionalWrapper(jtxl);
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.readOnly();
|
||||
} else if (this.jtxl != null) {
|
||||
return false;
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
public Propagation getPropagation() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.propagation();
|
||||
} else if (this.jtxl != null) {
|
||||
switch (this.jtxl.value()) {
|
||||
case MANDATORY:
|
||||
return Propagation.MANDATORY;
|
||||
case REQUIRED:
|
||||
return Propagation.REQUIRED;
|
||||
case REQUIRES_NEW:
|
||||
return Propagation.REQUIRES_NEW;
|
||||
case SUPPORTS:
|
||||
return Propagation.SUPPORTS;
|
||||
case NOT_SUPPORTED:
|
||||
return Propagation.NOT_SUPPORTED;
|
||||
case NEVER:
|
||||
return Propagation.NEVER;
|
||||
default:
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
public Isolation getIsolation() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.isolation();
|
||||
} else if (this.jtxl != null) {
|
||||
return Isolation.DEFAULT;
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
public int getTimeoutInSeconds() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.timeout();
|
||||
} else if (this.jtxl != null) {
|
||||
return 0;
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Throwable>[] getRollbackFor() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.rollbackFor();
|
||||
} else if (this.jtxl != null) {
|
||||
return this.jtxl.rollbackOn();
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Throwable>[] getNoRollbackFor() {
|
||||
if (this.stxl != null) {
|
||||
return this.stxl.noRollbackFor();
|
||||
} else if (this.jtxl != null) {
|
||||
return this.jtxl.dontRollbackOn();
|
||||
} else {
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.inteligr8.alfresco.annotations.aspect;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
@ -17,9 +18,13 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.TransactionalRetryable;
|
||||
import com.inteligr8.alfresco.annotations.TransactionalWrapper;
|
||||
import com.inteligr8.alfresco.annotations.util.JakartaTransactionalAnnotationAdapter;
|
||||
import com.inteligr8.alfresco.annotations.util.JtaTransactionalAnnotationAdapter;
|
||||
import com.inteligr8.alfresco.annotations.util.SpringTransactionalAnnotationAdapter;
|
||||
import com.inteligr8.alfresco.annotations.util.TransactionalAnnotationAdapter;
|
||||
|
||||
/**
|
||||
* This aspect implements the @Transactional and @TransactionalRetryable
|
||||
@ -54,16 +59,20 @@ public class RetryingTransactionAspect {
|
||||
public void isJtaTransactionalAnnotated() {
|
||||
}
|
||||
|
||||
@Pointcut("@annotation(jakarta.transaction.Transactional) && execution(* *(..))")
|
||||
public void isJakartaTransactionalAnnotated() {
|
||||
}
|
||||
|
||||
@Pointcut("@annotation(com.inteligr8.alfresco.annotations.TransactionalRetryable) && execution(* *(..))")
|
||||
public void isTransactionalRetryableAnnotated() {
|
||||
}
|
||||
|
||||
@Around("isTransactionalAnnotated() || isJtaTransactionalAnnotated() || isTransactionalRetryableAnnotated()")
|
||||
@Around("isTransactionalAnnotated() || isJtaTransactionalAnnotated() || isJakartaTransactionalAnnotated() || isTransactionalRetryableAnnotated()")
|
||||
public Object retryingTransactional(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
this.logger.trace("retryingTransactional({})", joinPoint);
|
||||
|
||||
Method method = this.getMethod(joinPoint);
|
||||
TransactionalWrapper txl = TransactionalWrapper.wrap(method);
|
||||
TransactionalAnnotationAdapter txl = this.wrapTransactionalAnnotation(method);
|
||||
TransactionalRetryable txtry = method.getAnnotation(TransactionalRetryable.class);
|
||||
|
||||
if (this.doCreateNewTxContext(txl) || this.isReadStateChange(txl)) {
|
||||
@ -77,6 +86,33 @@ public class RetryingTransactionAspect {
|
||||
}
|
||||
}
|
||||
|
||||
private TransactionalAnnotationAdapter wrapTransactionalAnnotation(Method method) {
|
||||
Annotation txl = method.getAnnotation(Transactional.class);
|
||||
if (txl != null)
|
||||
return new SpringTransactionalAnnotationAdapter((Transactional) txl);
|
||||
|
||||
txl = this.getOptionalAnnotation(method, "javax.transaction.Transactional");
|
||||
if (txl != null)
|
||||
return new JtaTransactionalAnnotationAdapter((javax.transaction.Transactional) txl);
|
||||
|
||||
txl = this.getOptionalAnnotation(method, "jakarta.transaction.Transactional");
|
||||
if (txl != null)
|
||||
return new JakartaTransactionalAnnotationAdapter((jakarta.transaction.Transactional) txl);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private <A extends Annotation> A getOptionalAnnotation(Method method, String fullyQualifiedAnnotationName) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<A> annotationClass = (Class<A>) Class.forName(fullyQualifiedAnnotationName);
|
||||
return method.getAnnotation(annotationClass);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
this.logger.trace("The {} annotation is not available in the classpath; assuming not set", fullyQualifiedAnnotationName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(ProceedingJoinPoint joinPoint) {
|
||||
if (!(joinPoint.getSignature() instanceof MethodSignature))
|
||||
throw new IllegalStateException("The @Transactional or @TransactionalRetryable annotations must be on methods");
|
||||
@ -85,7 +121,7 @@ public class RetryingTransactionAspect {
|
||||
return methodSig.getMethod();
|
||||
}
|
||||
|
||||
private boolean isReadStateChange(TransactionalWrapper txl) {
|
||||
private boolean isReadStateChange(TransactionalAnnotationAdapter txl) {
|
||||
if (txl == null)
|
||||
return false;
|
||||
|
||||
@ -114,7 +150,7 @@ public class RetryingTransactionAspect {
|
||||
return txtry != null;
|
||||
}
|
||||
|
||||
private boolean doCreateNewTxContext(TransactionalWrapper txl) {
|
||||
private boolean doCreateNewTxContext(TransactionalAnnotationAdapter txl) {
|
||||
if (txl == null) {
|
||||
return false;
|
||||
} else switch (txl.getPropagation()) {
|
||||
@ -159,7 +195,7 @@ public class RetryingTransactionAspect {
|
||||
}
|
||||
}
|
||||
|
||||
private Object execute(final ProceedingJoinPoint joinPoint, TransactionalWrapper txl, TransactionalRetryable txtry) throws Throwable {
|
||||
private Object execute(final ProceedingJoinPoint joinPoint, TransactionalAnnotationAdapter txl, TransactionalRetryable txtry) throws Throwable {
|
||||
RetryingTransactionCallback<Object> rtcallback = new RetryingTransactionCallback<Object>() {
|
||||
@Override
|
||||
public Object execute() throws Throwable {
|
||||
|
@ -0,0 +1,63 @@
|
||||
package com.inteligr8.alfresco.annotations.util;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
||||
public class JakartaTransactionalAnnotationAdapter implements TransactionalAnnotationAdapter {
|
||||
|
||||
private final Transactional txl;
|
||||
|
||||
public JakartaTransactionalAnnotationAdapter(Transactional txl) {
|
||||
this.txl = txl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Propagation getPropagation() {
|
||||
switch (this.txl.value()) {
|
||||
case MANDATORY:
|
||||
return Propagation.MANDATORY;
|
||||
case REQUIRED:
|
||||
return Propagation.REQUIRED;
|
||||
case REQUIRES_NEW:
|
||||
return Propagation.REQUIRES_NEW;
|
||||
case SUPPORTS:
|
||||
return Propagation.SUPPORTS;
|
||||
case NOT_SUPPORTED:
|
||||
return Propagation.NOT_SUPPORTED;
|
||||
case NEVER:
|
||||
return Propagation.NEVER;
|
||||
default:
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Isolation getIsolation() {
|
||||
return Isolation.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeoutInSeconds() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getRollbackFor() {
|
||||
return this.txl.rollbackOn();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getNoRollbackFor() {
|
||||
return this.txl.dontRollbackOn();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.inteligr8.alfresco.annotations.util;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
||||
public class JtaTransactionalAnnotationAdapter implements TransactionalAnnotationAdapter {
|
||||
|
||||
private final Transactional txl;
|
||||
|
||||
public JtaTransactionalAnnotationAdapter(Transactional txl) {
|
||||
this.txl = txl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Propagation getPropagation() {
|
||||
switch (this.txl.value()) {
|
||||
case MANDATORY:
|
||||
return Propagation.MANDATORY;
|
||||
case REQUIRED:
|
||||
return Propagation.REQUIRED;
|
||||
case REQUIRES_NEW:
|
||||
return Propagation.REQUIRES_NEW;
|
||||
case SUPPORTS:
|
||||
return Propagation.SUPPORTS;
|
||||
case NOT_SUPPORTED:
|
||||
return Propagation.NOT_SUPPORTED;
|
||||
case NEVER:
|
||||
return Propagation.NEVER;
|
||||
default:
|
||||
throw new IllegalStateException("This should never happen");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Isolation getIsolation() {
|
||||
return Isolation.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeoutInSeconds() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getRollbackFor() {
|
||||
return this.txl.rollbackOn();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getNoRollbackFor() {
|
||||
return this.txl.dontRollbackOn();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.inteligr8.alfresco.annotations.util;
|
||||
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public class SpringTransactionalAnnotationAdapter implements TransactionalAnnotationAdapter {
|
||||
|
||||
private final Transactional txl;
|
||||
|
||||
public SpringTransactionalAnnotationAdapter(Transactional txl) {
|
||||
this.txl = txl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return this.txl.readOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Propagation getPropagation() {
|
||||
return this.txl.propagation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Isolation getIsolation() {
|
||||
return this.txl.isolation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeoutInSeconds() {
|
||||
return this.txl.timeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getRollbackFor() {
|
||||
return this.txl.rollbackFor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Throwable>[] getNoRollbackFor() {
|
||||
return this.txl.noRollbackFor();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.inteligr8.alfresco.annotations.util;
|
||||
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
||||
public interface TransactionalAnnotationAdapter {
|
||||
|
||||
boolean isReadOnly();
|
||||
|
||||
Propagation getPropagation();
|
||||
|
||||
Isolation getIsolation();
|
||||
|
||||
int getTimeoutInSeconds();
|
||||
|
||||
Class<? extends Throwable>[] getRollbackFor();
|
||||
|
||||
Class<? extends Throwable>[] getNoRollbackFor();
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user