version upgrade; minor refactor
This commit is contained in:
parent
afcfbbc61a
commit
dc916ecdd6
BIN
metadata.keystore
Normal file
BIN
metadata.keystore
Normal file
Binary file not shown.
23
pom.xml
23
pom.xml
@ -10,6 +10,14 @@
|
||||
|
||||
<name>Annotations ACS Platform Module</name>
|
||||
<description>A module to support annotation-based development for Alfresco Content Services modules.</description>
|
||||
<url>https://bitbucket.org/inteligr8/annotations-platform-module</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007</name>
|
||||
<url>https://www.gnu.org/licenses/lgpl-3.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://bitbucket.org/inteligr8/annotations-platform-module.git</connection>
|
||||
@ -34,9 +42,10 @@
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
|
||||
<alfresco.sdk.version>4.2.0</alfresco.sdk.version>
|
||||
<alfresco.platform.version>6.2.0-ga</alfresco.platform.version>
|
||||
<aspectj.version>1.9.4</aspectj.version>
|
||||
<alfresco.sdk.version>4.8.0</alfresco.sdk.version>
|
||||
<alfresco.platform.version>7.4.2</alfresco.platform.version>
|
||||
<alfresco.platform.war.version>22.22</alfresco.platform.war.version>
|
||||
<aspectj.version>1.9.19</aspectj.version>
|
||||
<acs-platform.tomcat.opts>-javaagent:/var/lib/tomcat/dev/lib/aspectjweaver-${aspectj.version}.jar</acs-platform.tomcat.opts>
|
||||
</properties>
|
||||
|
||||
@ -63,7 +72,7 @@
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aspectj-platform-module</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -77,11 +86,11 @@
|
||||
<configuration>
|
||||
<tiles>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-rad-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.0.0,1.1.0)</tile>
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.1.0,1.2.0)</tile>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-module-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.0.0,1.1.0)</tile>
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.1.0,1.2.0)</tile>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-it-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.0.0,1.1.0)</tile>
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.1.0,1.2.0)</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
2
rad.sh
2
rad.sh
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
discoverArtifactId() {
|
||||
ARTIFACT_ID=`mvn -q -Dexpression=project.artifactId -DforceStdout help:evaluate | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g'`
|
||||
|
@ -5,10 +5,20 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to execute the annotated method
|
||||
* asynchronously. The execution may be performed any number of ways,
|
||||
* including a threaded execution or through a queuing service.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Asynchronous {
|
||||
|
||||
/**
|
||||
* Whether or not the execution is guaranteed.
|
||||
*
|
||||
* @return `true` if guaranteed; `false` otherwise
|
||||
*/
|
||||
boolean durable() default true;
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
package com.inteligr8.alfresco.annotations;
|
||||
|
||||
/**
|
||||
* This interface provides a way to specify a user for expected authorizations.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.Authorized
|
||||
*/
|
||||
public interface Authorizable {
|
||||
|
||||
/**
|
||||
* @return An ACS user ID.
|
||||
*/
|
||||
String authorizeAsUser();
|
||||
|
||||
}
|
||||
|
@ -5,10 +5,33 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to execute the annotated method
|
||||
* inside an ACS authorized context. This is how the execution can be elevated
|
||||
* to a service account or de-escalated to a user account.
|
||||
*
|
||||
* If the authorization is expected to be the same (the same user), then
|
||||
* another layer of authorization is **not** added.
|
||||
*
|
||||
* Use the Authorizable interface to provide a dynamic user ID for the
|
||||
* authorization context.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.Authorizable
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Authorized {
|
||||
|
||||
/**
|
||||
* The user ID to use for the authorization context.
|
||||
*
|
||||
* It is important to note that if the Authorizable interface is
|
||||
* implemented, then the value returned from its method will take
|
||||
* precedence over this one. This capability is useful for to support
|
||||
* dynamic user authorization contexts.
|
||||
*
|
||||
* @return An ACS user ID; empty will be treated as `system`.
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,14 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to execute the annotated method
|
||||
* inside an ACS `system` authorized context. This is the highest privileged
|
||||
* execution.
|
||||
*
|
||||
* If the authorization is expected to be the same (remains `system`), then
|
||||
* another layer of authorization is **not** added.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface AuthorizedAsSystem {
|
||||
|
@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to skip execution if the annotated
|
||||
* parameter or any annotated method parameter is a child association that is
|
||||
* not primary.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
|
@ -5,6 +5,12 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to skip execution if the annotated
|
||||
* parameter or any annotated method parameter is a node reference and it does
|
||||
* not exist. Unless cached, this will result in the framework consulting with
|
||||
* the database.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
|
@ -5,6 +5,15 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to skip execution if the annotated
|
||||
* parameter or any annotated method parameter is a node reference and it does
|
||||
* not have the specified aspect. Unless cached, this will result in the
|
||||
* framework consulting with the database.
|
||||
*
|
||||
* This includes support for checking the child node reference of a
|
||||
* parent-child association and both the source/target of a peer association.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
@ -12,6 +21,9 @@ import java.lang.annotation.Target;
|
||||
})
|
||||
public @interface IfNodeHasAspect {
|
||||
|
||||
/**
|
||||
* @return An ACS aspect in the Alfresco QName prefixed format (e.g. `cm:auditable`).
|
||||
*/
|
||||
String aspect() default "";
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,15 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to skip execution if the annotated
|
||||
* parameter or any annotated method parameter is a node reference and it is
|
||||
* not of the specified type. Unless cached, this will result in the framework
|
||||
* consulting with the database.
|
||||
*
|
||||
* This includes support for checking the child node reference of a
|
||||
* parent-child association and both the source/target of a peer association.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
@ -12,6 +21,9 @@ import java.lang.annotation.Target;
|
||||
})
|
||||
public @interface IfNodeOfType {
|
||||
|
||||
/**
|
||||
* @return An ACS node type in the Alfresco QName prefixed format (e.g. `cm:content`).
|
||||
*/
|
||||
String type() default "";
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to skip execution if the annotated
|
||||
* parameter or any annotated method parameter is `null`.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
|
@ -7,7 +7,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ClusterSynchronized {
|
||||
public @interface JobSynchronized {
|
||||
|
||||
String value() default "";
|
||||
|
@ -5,20 +5,48 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to execute the annotated method inside a
|
||||
* pool of threads.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Threaded {
|
||||
|
||||
/**
|
||||
* @return A name for the thread pool.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* @return A number of threads to execute.
|
||||
*/
|
||||
int threads() default 1;
|
||||
|
||||
/**
|
||||
* @return A maximum number of threads to execute at any one time; the thread pool size.
|
||||
*/
|
||||
int concurrency() default 0;
|
||||
|
||||
/**
|
||||
* @return A Java thread priority for all the threads.
|
||||
*/
|
||||
int priority() default Thread.NORM_PRIORITY;
|
||||
|
||||
/**
|
||||
* Whether or not the calling thread should wait for all the threads to complete.
|
||||
*
|
||||
* @return `true` to wait; `false` to return immediately.
|
||||
*/
|
||||
boolean join() default false;
|
||||
|
||||
/**
|
||||
* How long the calling thread should wait before returning. If a timeout
|
||||
* is reached, a TimeoutException will be thrown. If this is not desired,
|
||||
* then `join()` should return `false`.
|
||||
*
|
||||
* @return A number of milliseconds to wait; 0 waits indefinitely
|
||||
*/
|
||||
long joinWaitMillis() default 0L;
|
||||
|
||||
}
|
||||
|
@ -5,16 +5,41 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
|
||||
/**
|
||||
* This annotation tells the framework to wrap the annotated method inside an
|
||||
* ACS API retryable transaction. This may be used in conjunction with the
|
||||
* Spring Transactional annotation.
|
||||
*
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface TransactionalRetryable {
|
||||
|
||||
/**
|
||||
* @return A number of retries; -1 for ACS API default (unlimited).
|
||||
* @see RetryingTransactionHelper#setMaxRetries(int)
|
||||
*/
|
||||
int maxRetries() default -1;
|
||||
|
||||
|
||||
/**
|
||||
* @return A minimum number of milliseconds to wait between retries; -1 for ACS API default (200 ms).
|
||||
* @see RetryingTransactionHelper#setMinRetryWaitMs(int)
|
||||
*/
|
||||
int minRetryWaitInMillis() default -1;
|
||||
|
||||
|
||||
/**
|
||||
* @return A maximum number of milliseconds to wait between retries; -1 for ACS API default (2000 ms).
|
||||
* @see RetryingTransactionHelper#setMaxRetryWaitMs(int)
|
||||
*/
|
||||
int maxRetryWaitInMillis() default -1;
|
||||
|
||||
|
||||
/**
|
||||
* @return A number of milliseconds to progressively add to the wait after each attempt; -1 for ACS API default (100 ms).
|
||||
* @see RetryingTransactionHelper#setRetryWaitIncrementMs(int)
|
||||
*/
|
||||
int incRetryWaitInMillis() default -1;
|
||||
|
||||
}
|
||||
|
@ -2,11 +2,21 @@ package com.inteligr8.alfresco.annotations.aspect;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AbstractMethodAspect<A extends Annotation> extends AbstractWarnOnceService {
|
||||
public abstract class AbstractMethodAspect<A extends Annotation> extends AbstractWarnOnceService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private Set<Pair<String, String>> warned = new HashSet<>();
|
||||
|
||||
protected A getAnnotation(ProceedingJoinPoint joinPoint, Class<A> annotationClass, boolean warnReturn, boolean warnThrows) {
|
||||
Method method = this.getMethod(joinPoint, annotationClass, warnReturn, warnThrows);
|
||||
@ -49,5 +59,26 @@ public class AbstractMethodAspect<A extends Annotation> extends AbstractWarnOnce
|
||||
return obj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean validate(ProceedingJoinPoint joinPoint, Class<A> annotationClass,
|
||||
Collection<Class<? extends Annotation>> ignoredAnnotationClasses, Collection<Class<? extends Annotation>> disallowedAnnotationClasses) {
|
||||
Method method = this.getMethod(joinPoint, annotationClass, false, false);
|
||||
|
||||
for (Class<? extends Annotation> a : ignoredAnnotationClasses) {
|
||||
if (method.isAnnotationPresent(a)) {
|
||||
if (this.warned.add(Pair.of(a.getName(), annotationClass.getName())))
|
||||
this.logger.warn("@{} cannot be used on the same method as @{}; ignoring annotation", a.getSimpleName(), annotationClass.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
for (Class<? extends Annotation> a : disallowedAnnotationClasses) {
|
||||
if (method.isAnnotationPresent(a)) {
|
||||
this.logger.error("@{} cannot be used on the same method as @{}", a.getSimpleName(), annotationClass.getSimpleName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AbstractWarnOnceService {
|
||||
public abstract class AbstractWarnOnceService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
|
@ -14,10 +14,13 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import com.inteligr8.alfresco.annotations.Asynchronous;
|
||||
import com.inteligr8.alfresco.annotations.service.AsyncService;
|
||||
|
||||
/**
|
||||
* This aspect implements the @Asynchronous annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.Asynchronous
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.AsyncAspect, *")
|
||||
//@Order(Ordered.HIGHEST_PRECEDENCE + Byte.MAX_VALUE)
|
||||
//@Component
|
||||
public class AsyncAspect extends AbstractMethodAspect<Asynchronous> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
@ -18,10 +18,14 @@ import com.inteligr8.alfresco.annotations.Authorizable;
|
||||
import com.inteligr8.alfresco.annotations.Authorized;
|
||||
import com.inteligr8.alfresco.annotations.AuthorizedAsSystem;
|
||||
|
||||
/**
|
||||
* This aspect implements the Authorized and AuthorizedAsSystem annotations.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.Authorized
|
||||
* @see com.inteligr8.alfresco.annotations.AuthorizedAsSystem
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.AuthorizedAspect, com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect")
|
||||
//@Order(Ordered.HIGHEST_PRECEDENCE + Short.MAX_VALUE)
|
||||
//@Component
|
||||
public class AuthorizedAspect {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@ -73,7 +77,7 @@ public class AuthorizedAspect {
|
||||
|
||||
Authorized runAsAnnotation = method.getAnnotation(Authorized.class);
|
||||
String runAs = StringUtils.trimToNull(runAsAnnotation.value());
|
||||
if (runAs != null) {
|
||||
if (runAs != null && runAs.length() > 0) {
|
||||
this.logger.trace("The @Authorized method '{}' must run as: {}", method, runAs);
|
||||
return runAs;
|
||||
}
|
||||
|
@ -12,8 +12,12 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.IfChildAssociationIsPrimary;
|
||||
|
||||
/**
|
||||
* This aspect implements the IfChildAssociationIsPrimary annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.IfChildAssociationIsPrimary
|
||||
*/
|
||||
@Aspect
|
||||
//@Component
|
||||
public class ChildIsPrimaryAspect extends AbstractMethodOrParameterAspect<IfChildAssociationIsPrimary> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
@ -14,13 +14,16 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.ClusterSynchronized;
|
||||
import com.inteligr8.alfresco.annotations.JobSynchronized;
|
||||
|
||||
/**
|
||||
* This aspect implements the JobSynchronized annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.JobSynchronized
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.ClusterSynchronizedAspect")
|
||||
//@Component
|
||||
//@Order(Ordered.LOWEST_PRECEDENCE - Byte.MAX_VALUE)
|
||||
public class ClusterSynchronizedAspect extends AbstractMethodAspect<ClusterSynchronized> {
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.JobLockAspect")
|
||||
public class JobLockAspect extends AbstractMethodAspect<JobSynchronized> {
|
||||
|
||||
private static final String NS = "http://inteligr8.com/alfresco/model";
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@ -28,33 +31,33 @@ public class ClusterSynchronizedAspect extends AbstractMethodAspect<ClusterSynch
|
||||
@Autowired
|
||||
private JobLockService jobLockService;
|
||||
|
||||
@Pointcut("@annotation(com.inteligr8.alfresco.annotations.ClusterSynchronized) && execution(* *(..))")
|
||||
public void isClusterSyncAnnotated() {
|
||||
@Pointcut("@annotation(com.inteligr8.alfresco.annotations.JobSynchronized) && execution(* *(..))")
|
||||
public void isJobSyncAnnotated() {
|
||||
}
|
||||
|
||||
@Around("isClusterSyncAnnotated()")
|
||||
public Object clusterSync(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
this.logger.trace("clusterSync({})", joinPoint);
|
||||
@Around("isJobSyncAnnotated()")
|
||||
public Object jobSync(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
this.logger.trace("jobSync({})", joinPoint);
|
||||
|
||||
Method method = this.getMethod(joinPoint, ClusterSynchronized.class, false, false);
|
||||
ClusterSynchronized clusterSync = method.getAnnotation(ClusterSynchronized.class);
|
||||
Method method = this.getMethod(joinPoint, JobSynchronized.class, false, false);
|
||||
JobSynchronized clusterSync = method.getAnnotation(JobSynchronized.class);
|
||||
|
||||
QName lockQName = this.getLockQName(clusterSync, method);
|
||||
|
||||
this.logger.debug("Acquiring cluster lock: {}", lockQName);
|
||||
this.logger.debug("Acquiring job lock: {}", lockQName);
|
||||
String lockToken = this.jobLockService.getLock(lockQName, clusterSync.lockTimeoutInMillis(),
|
||||
clusterSync.acquireWaitBetweenRetriesInMillis(), clusterSync.acquireMaxRetries());
|
||||
try {
|
||||
this.logger.trace("Acquired cluster lock: {}", lockQName);
|
||||
this.logger.trace("Acquired job lock: {}", lockQName);
|
||||
|
||||
return joinPoint.proceed();
|
||||
} finally {
|
||||
this.logger.debug("Releasing cluster lock: {}", lockQName);
|
||||
this.logger.debug("Releasing job lock: {}", lockQName);
|
||||
this.jobLockService.releaseLock(lockToken, lockQName);
|
||||
}
|
||||
}
|
||||
|
||||
private QName getLockQName(ClusterSynchronized clusterSync, Method method) {
|
||||
private QName getLockQName(JobSynchronized clusterSync, Method method) {
|
||||
String lockName = StringUtils.trimToNull(clusterSync.value());
|
||||
if (lockName != null) {
|
||||
return QName.createQNameWithValidLocalName(NS, lockName);
|
@ -1,16 +1,12 @@
|
||||
package com.inteligr8.alfresco.annotations.aspect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@ -25,12 +21,16 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.NodeAspectConstrainable;
|
||||
import com.inteligr8.alfresco.annotations.IfNodeHasAspect;
|
||||
import com.inteligr8.alfresco.annotations.NodeAspectConstrainable;
|
||||
|
||||
/**
|
||||
* This aspect implements the IfNodeHasAspect annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.IfNodeHasAspect
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.NodeAspectAspect")
|
||||
//@Component
|
||||
public class NodeAspectAspect extends QNameBasedAspect<IfNodeHasAspect> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@ -128,36 +128,5 @@ public class NodeAspectAspect extends QNameBasedAspect<IfNodeHasAspect> {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Collection<NodeRef> extractNodeRefs(Object obj) {
|
||||
if (obj instanceof NodeRef) {
|
||||
NodeRef nodeRef = (NodeRef) obj;
|
||||
return Collections.singleton(nodeRef);
|
||||
} else if (obj instanceof ChildAssociationRef) {
|
||||
ChildAssociationRef childAssocRef = (ChildAssociationRef) obj;
|
||||
return Collections.singleton(childAssocRef.getChildRef());
|
||||
} else if (obj instanceof AssociationRef) {
|
||||
AssociationRef assocRef = (AssociationRef) obj;
|
||||
return Arrays.asList(assocRef.getSourceRef(), assocRef.getTargetRef());
|
||||
} else if (obj instanceof Collection<?>) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Collection<?>) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else if (obj instanceof Object[]) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Object[]) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,11 @@
|
||||
package com.inteligr8.alfresco.annotations.aspect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@ -28,9 +23,13 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import com.inteligr8.alfresco.annotations.IfNodeOfType;
|
||||
import com.inteligr8.alfresco.annotations.NodeTypeConstrainable;
|
||||
|
||||
/**
|
||||
* This aspect implements the IfNodeOfType annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.IfNodeOfType
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.NodeTypeAspect")
|
||||
//@Component
|
||||
public class NodeTypeAspect extends QNameBasedAspect<IfNodeOfType> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@ -128,36 +127,5 @@ public class NodeTypeAspect extends QNameBasedAspect<IfNodeOfType> {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Collection<NodeRef> extractNodeRefs(Object obj) {
|
||||
if (obj instanceof NodeRef) {
|
||||
NodeRef nodeRef = (NodeRef) obj;
|
||||
return Collections.singleton(nodeRef);
|
||||
} else if (obj instanceof ChildAssociationRef) {
|
||||
ChildAssociationRef childAssocRef = (ChildAssociationRef) obj;
|
||||
return Collections.singleton(childAssocRef.getChildRef());
|
||||
} else if (obj instanceof AssociationRef) {
|
||||
AssociationRef assocRef = (AssociationRef) obj;
|
||||
return Arrays.asList(assocRef.getSourceRef(), assocRef.getTargetRef());
|
||||
} else if (obj instanceof Collection<?>) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Collection<?>) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else if (obj instanceof Object[]) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Object[]) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,9 +12,12 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.IfNotNull;
|
||||
|
||||
/**
|
||||
* This aspect implements the IfNotNull annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.IfNotNull
|
||||
*/
|
||||
@Aspect
|
||||
//@Order(Ordered.HIGHEST_PRECEDENCE + 64)
|
||||
//@Component
|
||||
public class NotNullAspect {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
@ -22,9 +22,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.IfNodeExists;
|
||||
|
||||
/**
|
||||
* This aspect implements the IfNodeExists annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.IfNodeExists
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.OperableNodeAspect")
|
||||
//@Component
|
||||
public class OperableNodeAspect extends AbstractMethodOrParameterAspect<IfNodeExists> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
@ -1,14 +1,20 @@
|
||||
package com.inteligr8.alfresco.annotations.aspect;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.alfresco.repo.cache.DefaultSimpleCache;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
@ -76,6 +82,37 @@ public abstract class QNameBasedAspect<T extends Annotation> extends AbstractMet
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<NodeRef> extractNodeRefs(Object obj) {
|
||||
if (obj instanceof NodeRef) {
|
||||
NodeRef nodeRef = (NodeRef) obj;
|
||||
return Collections.singleton(nodeRef);
|
||||
} else if (obj instanceof ChildAssociationRef) {
|
||||
ChildAssociationRef childAssocRef = (ChildAssociationRef) obj;
|
||||
return Collections.singleton(childAssocRef.getChildRef());
|
||||
} else if (obj instanceof AssociationRef) {
|
||||
AssociationRef assocRef = (AssociationRef) obj;
|
||||
return Arrays.asList(assocRef.getSourceRef(), assocRef.getTargetRef());
|
||||
} else if (obj instanceof Collection<?>) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Collection<?>) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else if (obj instanceof Object[]) {
|
||||
Set<NodeRef> nodeRefs = new LinkedHashSet<>();
|
||||
for (Object o : ((Object[]) obj)) {
|
||||
Collection<NodeRef> subNodeRefs = this.extractNodeRefs(o);
|
||||
if (subNodeRefs != null)
|
||||
nodeRefs.addAll(subNodeRefs);
|
||||
}
|
||||
return nodeRefs;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface QNameBasedCallback<T> {
|
||||
|
@ -21,10 +21,24 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.inteligr8.alfresco.annotations.TransactionalRetryable;
|
||||
|
||||
/**
|
||||
* This aspect implements the @Transactional and @TransactionalRetryable
|
||||
* annotations.
|
||||
*
|
||||
* Most notably, it implements the Spring @Transactional annotation, so it
|
||||
* works when used within ACS modules. Both could be used; or just either one.
|
||||
* Each situation has a different meaning.
|
||||
*
|
||||
* - Without @TransactionalRetryable, it will not automatically retry due to
|
||||
* expected concurrency issues.
|
||||
* - Without @Transactional, it will be like a readonly
|
||||
* @Transactional(SUPPORTS)
|
||||
*
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
* @see com.inteligr8.alfresco.annotations.TransactionalRetryable
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.AuthorizedAspect, com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect")
|
||||
//@Component
|
||||
//@Order(Ordered.LOWEST_PRECEDENCE - Short.MAX_VALUE)
|
||||
public class RetryingTransactionAspect {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
@ -9,6 +9,7 @@ import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
@ -24,10 +25,13 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.inteligr8.alfresco.annotations.Threadable;
|
||||
import com.inteligr8.alfresco.annotations.Threaded;
|
||||
|
||||
/**
|
||||
* This aspect implements the @Threaded annotation.
|
||||
*
|
||||
* @see com.inteligr8.alfresco.annotations.Threaded
|
||||
*/
|
||||
@Aspect
|
||||
@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.AsyncAspect, com.inteligr8.alfresco.annotations.aspect.ThreadedAspect, *")
|
||||
//@Order(Ordered.HIGHEST_PRECEDENCE + Byte.MAX_VALUE)
|
||||
//@Component
|
||||
public class ThreadedAspect extends AbstractMethodAspect<Threaded> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
@ -53,6 +57,7 @@ public class ThreadedAspect extends AbstractMethodAspect<Threaded> {
|
||||
this.logger.trace("threaded({})", joinPoint);
|
||||
|
||||
Threaded threaded = this.getAnnotation(joinPoint, Threaded.class, true, true);
|
||||
|
||||
MergedThreadConfiguration threadConfig = new MergedThreadConfiguration(joinPoint, threaded);
|
||||
|
||||
ThreadFactoryBuilder tfbuilder = new ThreadFactoryBuilder()
|
||||
@ -86,13 +91,16 @@ public class ThreadedAspect extends AbstractMethodAspect<Threaded> {
|
||||
|
||||
if (threaded.join()) {
|
||||
long waitMillis = threaded.joinWaitMillis() == 0L ? 300000L : threaded.joinWaitMillis();
|
||||
do {
|
||||
while (true) {
|
||||
this.logger.debug("Blocking this thread until subthreads finish: {}", Thread.currentThread().getId());
|
||||
if (threadExecutor.awaitTermination(waitMillis, TimeUnit.MILLISECONDS)) {
|
||||
if (!threadExecutor.awaitTermination(waitMillis, TimeUnit.MILLISECONDS)) {
|
||||
if (threaded.joinWaitMillis() > 0L)
|
||||
throw new TimeoutException();
|
||||
} else {
|
||||
this.logger.trace("Subthreads finished; unblocking this thread: {}", Thread.currentThread().getId());
|
||||
break;
|
||||
}
|
||||
} while (threaded.joinWaitMillis() == 0L);
|
||||
}
|
||||
|
||||
this.logger.debug("Subthreads running: {}; unblocking this thread: {}", threadExecutor.getActiveCount(), Thread.currentThread().getId());
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ import org.alfresco.service.transaction.TransactionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This bean implements a standard TransactionManager for ACS.
|
||||
*/
|
||||
@Component
|
||||
public class AlfrescoTransactionManager implements TransactionManager {
|
||||
|
||||
|
@ -30,7 +30,6 @@ import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
@ -48,8 +47,8 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.activemq.ActiveMQXAConnectionFactory;
|
||||
import org.apache.activemq.jms.pool.XaPooledConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.jms.pool.PooledConnectionFactory;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.quartz.JobKey;
|
||||
@ -79,7 +78,7 @@ import com.inteligr8.alfresco.annotations.service.AsyncProcessException;
|
||||
import com.inteligr8.alfresco.annotations.service.AsyncService;
|
||||
|
||||
/**
|
||||
* This class provides integration with MQ for the asynchronous filing of nodes.
|
||||
* This class provides integration with MQ for the asynchronous method executions.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
@ -98,7 +97,6 @@ public class MqAsyncService extends AbstractLifecycleBean implements AsyncServic
|
||||
protected int workerThreads;
|
||||
|
||||
@Value("${inteligr8.async.mq.url}")
|
||||
//@Value("${messaging.broker.url}")
|
||||
protected String url;
|
||||
|
||||
@Value("${inteligr8.async.mq.username}")
|
||||
@ -137,12 +135,9 @@ public class MqAsyncService extends AbstractLifecycleBean implements AsyncServic
|
||||
@Autowired
|
||||
protected TransactionService txService;
|
||||
|
||||
@Autowired
|
||||
protected TransactionManager txManager;
|
||||
|
||||
private String hostname;
|
||||
|
||||
private XaPooledConnectionFactory factory;
|
||||
private PooledConnectionFactory factory;
|
||||
|
||||
private SimpleCache<Pair<Class<?>, String>, Method> methodCache;
|
||||
|
||||
@ -164,12 +159,11 @@ public class MqAsyncService extends AbstractLifecycleBean implements AsyncServic
|
||||
this.hostname = "unknown";
|
||||
}
|
||||
|
||||
ActiveMQXAConnectionFactory factory = new ActiveMQXAConnectionFactory(this.url);
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(this.url);
|
||||
|
||||
XaPooledConnectionFactory pool = new XaPooledConnectionFactory();
|
||||
PooledConnectionFactory pool = new PooledConnectionFactory();
|
||||
pool.setConnectionFactory(factory);
|
||||
pool.setMaxConnections(this.maxConnections);
|
||||
pool.setTransactionManager(this.txManager);
|
||||
pool.start();
|
||||
|
||||
this.factory = pool;
|
||||
|
@ -33,7 +33,8 @@ import com.inteligr8.alfresco.annotations.service.AsyncProcessException;
|
||||
import com.inteligr8.alfresco.annotations.service.AsyncService;
|
||||
|
||||
/**
|
||||
* This class provides a non-persistent alternative to MQ for asynchronous execution.
|
||||
* This class provides a non-persistent alternative to MQ for asynchronous method
|
||||
* execution.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.AsyncAspect" />
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.AuthorizedAspect" />
|
||||
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.ClusterSynchronizedAspect" />
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.JobLockAspect" />
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.OperableNodeAspect" />
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.NodeTypeAspect" />
|
||||
<aspect name="com.inteligr8.alfresco.annotations.aspect.NodeAspectAspect" />
|
||||
|
@ -0,0 +1,2 @@
|
||||
logger.inteligr8-annotations.name=com.inteligr8.alfresco.annotations
|
||||
logger.inteligr8-annotations.level=info
|
@ -1,4 +1,9 @@
|
||||
module.id=${project.artifactId}
|
||||
module.id=${project.groupId}.${project.artifactId}
|
||||
module.title=${project.name}
|
||||
module.description=${project.description}
|
||||
module.version=${project.version}
|
||||
|
||||
module.repo.version.min=6.0
|
||||
#module.repo.version.max=
|
||||
|
||||
module.depends.aspectj-platform-module=1.0-*
|
||||
|
@ -6,37 +6,52 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Component
|
||||
public class ClusterSynchronizedTest extends AbstractLifecycleBean {
|
||||
public class JobSynchronizedTest extends AbstractLifecycleBean {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event) {
|
||||
MutableInt threadsRun = new MutableInt();
|
||||
this.simpleLock();
|
||||
this.threadThenLock(threadsRun);
|
||||
this.threadAndLock(threadsRun);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event) {
|
||||
}
|
||||
|
||||
@Threaded(name = "cluster-sync", threads = 5, join = true)
|
||||
@Transactional
|
||||
@ClusterSynchronized
|
||||
private void threadThenLock(MutableInt threadsRun) {
|
||||
@JobSynchronized
|
||||
private void simpleLock() {
|
||||
this.logger.debug("simpleLock()");
|
||||
}
|
||||
|
||||
@Threaded(name = "job-sync", threads = 5, join = true)
|
||||
@JobSynchronized
|
||||
private void threadAndLock(MutableInt threadsRun) {
|
||||
this.lock(threadsRun);
|
||||
}
|
||||
|
||||
@Threaded(name = "job-sync", threads = 5, join = true)
|
||||
private void threadThenLock(MutableInt threadsRun) {
|
||||
this.lock(threadsRun);
|
||||
}
|
||||
|
||||
@JobSynchronized
|
||||
private void lock(MutableInt threadsRun) {
|
||||
this.locked(threadsRun);
|
||||
}
|
||||
|
||||
private void locked(MutableInt threadsRun) {
|
||||
int t = threadsRun.intValue();
|
||||
this.logger.debug("After start of a mutually exclusive execution block: {}", t);
|
||||
|
||||
try {
|
||||
Thread.sleep(200L);
|
||||
Thread.sleep(100L);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
|
@ -6,3 +6,6 @@ log4j.logger.org.springframework.extensions.webscripts.ScriptLogger=debug
|
||||
|
||||
# non-WebScript JavaScript execution debugging
|
||||
log4j.logger.org.alfresco.repo.jscript.ScriptLogger=debug
|
||||
|
||||
# Module importing
|
||||
#log4j.logger.org.alfresco.repo.module.ImporterModuleComponent=trace
|
||||
|
@ -0,0 +1,12 @@
|
||||
# Module debugging
|
||||
logger.inteligr8-annotations.level=trace
|
||||
|
||||
# WebScript debugging
|
||||
logger.springframework-extensions-webscripts-ScriptLogger.level=debug
|
||||
|
||||
# non-WebScript JavaScript execution debugging
|
||||
logger.alfresco-repo-jscript-ScriptLogger.level=debug
|
||||
|
||||
# Module importing
|
||||
#logger.alfresco-repo-module-importer.name=org.alfresco.repo.module.ImporterModuleComponent
|
||||
#logger.alfresco-repo-module-importer.level=trace
|
Loading…
x
Reference in New Issue
Block a user