diff --git a/metadata.keystore b/metadata.keystore
new file mode 100644
index 0000000..2c2a1d9
Binary files /dev/null and b/metadata.keystore differ
diff --git a/pom.xml b/pom.xml
index 6662b2c..eb0a3ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,6 +10,14 @@
Annotations ACS Platform Module
A module to support annotation-based development for Alfresco Content Services modules.
+ https://bitbucket.org/inteligr8/annotations-platform-module
+
+
+
+ GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007
+ https://www.gnu.org/licenses/lgpl-3.0.txt
+
+
scm:git:https://bitbucket.org/inteligr8/annotations-platform-module.git
@@ -34,9 +42,10 @@
8
8
- 4.2.0
- 6.2.0-ga
- 1.9.4
+ 4.8.0
+ 7.4.2
+ 22.22
+ 1.9.19
-javaagent:/var/lib/tomcat/dev/lib/aspectjweaver-${aspectj.version}.jar
@@ -63,7 +72,7 @@
com.inteligr8.alfresco
aspectj-platform-module
- 1.0-SNAPSHOT
+ 1.0.0
@@ -77,11 +86,11 @@
- com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.0.0,1.1.0)
+ com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.1.0,1.2.0)
- com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.0.0,1.1.0)
+ com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.1.0,1.2.0)
- com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.0.0,1.1.0)
+ com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.1.0,1.2.0)
diff --git a/rad.sh b/rad.sh
index aa08375..3c7c2fa 100644
--- a/rad.sh
+++ b/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'`
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/Asynchronous.java b/src/main/java/com/inteligr8/alfresco/annotations/Asynchronous.java
index cd7b3c2..5a5c321 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/Asynchronous.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/Asynchronous.java
@@ -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;
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/Authorizable.java b/src/main/java/com/inteligr8/alfresco/annotations/Authorizable.java
index 13c2d82..c2a1944 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/Authorizable.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/Authorizable.java
@@ -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();
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/Authorized.java b/src/main/java/com/inteligr8/alfresco/annotations/Authorized.java
index 8af3698..8c3b925 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/Authorized.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/Authorized.java
@@ -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 "";
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/AuthorizedAsSystem.java b/src/main/java/com/inteligr8/alfresco/annotations/AuthorizedAsSystem.java
index 7ddecac..5e38357 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/AuthorizedAsSystem.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/AuthorizedAsSystem.java
@@ -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 {
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/IfChildAssociationIsPrimary.java b/src/main/java/com/inteligr8/alfresco/annotations/IfChildAssociationIsPrimary.java
index 97a8db1..deb3287 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/IfChildAssociationIsPrimary.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/IfChildAssociationIsPrimary.java
@@ -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,
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeExists.java b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeExists.java
index cdf27d9..e86c15f 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeExists.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeExists.java
@@ -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,
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeHasAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeHasAspect.java
index 723530b..c86a17f 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeHasAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeHasAspect.java
@@ -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 "";
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeOfType.java b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeOfType.java
index 2f03e1b..f403795 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/IfNodeOfType.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/IfNodeOfType.java
@@ -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 "";
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/IfNotNull.java b/src/main/java/com/inteligr8/alfresco/annotations/IfNotNull.java
index e03e5ca..c37b79e 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/IfNotNull.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/IfNotNull.java
@@ -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,
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/ClusterSynchronized.java b/src/main/java/com/inteligr8/alfresco/annotations/JobSynchronized.java
similarity index 91%
rename from src/main/java/com/inteligr8/alfresco/annotations/ClusterSynchronized.java
rename to src/main/java/com/inteligr8/alfresco/annotations/JobSynchronized.java
index 775f864..c718258 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/ClusterSynchronized.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/JobSynchronized.java
@@ -7,7 +7,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
-public @interface ClusterSynchronized {
+public @interface JobSynchronized {
String value() default "";
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/Threaded.java b/src/main/java/com/inteligr8/alfresco/annotations/Threaded.java
index 438ab56..b243d3a 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/Threaded.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/Threaded.java
@@ -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;
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/TransactionalRetryable.java b/src/main/java/com/inteligr8/alfresco/annotations/TransactionalRetryable.java
index 1d2aa79..2823e66 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/TransactionalRetryable.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/TransactionalRetryable.java
@@ -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;
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractMethodAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractMethodAspect.java
index 60fcfbb..000c0d9 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractMethodAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractMethodAspect.java
@@ -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 extends AbstractWarnOnceService {
+public abstract class AbstractMethodAspect extends AbstractWarnOnceService {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ private Set> warned = new HashSet<>();
protected A getAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass, boolean warnReturn, boolean warnThrows) {
Method method = this.getMethod(joinPoint, annotationClass, warnReturn, warnThrows);
@@ -49,5 +59,26 @@ public class AbstractMethodAspect extends AbstractWarnOnce
return obj.toString();
}
}
+
+ protected boolean validate(ProceedingJoinPoint joinPoint, Class annotationClass,
+ Collection> ignoredAnnotationClasses, Collection> 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;
+ }
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractWarnOnceService.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractWarnOnceService.java
index d14e6f0..f0c7199 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractWarnOnceService.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AbstractWarnOnceService.java
@@ -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());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AsyncAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AsyncAspect.java
index cd653c3..f882b99 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AsyncAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AsyncAspect.java
@@ -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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AuthorizedAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AuthorizedAspect.java
index 4d2ba02..f887e61 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/AuthorizedAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/AuthorizedAspect.java
@@ -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;
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ChildIsPrimaryAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/ChildIsPrimaryAspect.java
index 3a54f32..d793356 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ChildIsPrimaryAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/ChildIsPrimaryAspect.java
@@ -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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ClusterSynchronizedAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/JobLockAspect.java
similarity index 61%
rename from src/main/java/com/inteligr8/alfresco/annotations/aspect/ClusterSynchronizedAspect.java
rename to src/main/java/com/inteligr8/alfresco/annotations/aspect/JobLockAspect.java
index 2d48225..f80f3bb 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ClusterSynchronizedAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/JobLockAspect.java
@@ -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 {
+@DeclarePrecedence("com.inteligr8.alfresco.annotations.aspect.RetryingTransactionAspect, com.inteligr8.alfresco.annotations.aspect.JobLockAspect")
+public class JobLockAspect extends AbstractMethodAspect {
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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -128,36 +128,5 @@ public class NodeAspectAspect extends QNameBasedAspect {
}
});
}
-
- private Collection 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 nodeRefs = new LinkedHashSet<>();
- for (Object o : ((Collection>) obj)) {
- Collection subNodeRefs = this.extractNodeRefs(o);
- if (subNodeRefs != null)
- nodeRefs.addAll(subNodeRefs);
- }
- return nodeRefs;
- } else if (obj instanceof Object[]) {
- Set nodeRefs = new LinkedHashSet<>();
- for (Object o : ((Object[]) obj)) {
- Collection subNodeRefs = this.extractNodeRefs(o);
- if (subNodeRefs != null)
- nodeRefs.addAll(subNodeRefs);
- }
- return nodeRefs;
- } else {
- return null;
- }
- }
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/NodeTypeAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/NodeTypeAspect.java
index a89eb04..c631539 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/NodeTypeAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/NodeTypeAspect.java
@@ -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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -128,36 +127,5 @@ public class NodeTypeAspect extends QNameBasedAspect {
}
});
}
-
- private Collection 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 nodeRefs = new LinkedHashSet<>();
- for (Object o : ((Collection>) obj)) {
- Collection subNodeRefs = this.extractNodeRefs(o);
- if (subNodeRefs != null)
- nodeRefs.addAll(subNodeRefs);
- }
- return nodeRefs;
- } else if (obj instanceof Object[]) {
- Set nodeRefs = new LinkedHashSet<>();
- for (Object o : ((Object[]) obj)) {
- Collection subNodeRefs = this.extractNodeRefs(o);
- if (subNodeRefs != null)
- nodeRefs.addAll(subNodeRefs);
- }
- return nodeRefs;
- } else {
- return null;
- }
- }
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/NotNullAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/NotNullAspect.java
index 3a13747..b32eb20 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/NotNullAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/NotNullAspect.java
@@ -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());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/OperableNodeAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/OperableNodeAspect.java
index c477621..73130b4 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/OperableNodeAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/OperableNodeAspect.java
@@ -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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/QNameBasedAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/QNameBasedAspect.java
index 2a944e7..fb66d38 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/QNameBasedAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/QNameBasedAspect.java
@@ -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 extends AbstractMet
}
}
+ protected Collection 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 nodeRefs = new LinkedHashSet<>();
+ for (Object o : ((Collection>) obj)) {
+ Collection subNodeRefs = this.extractNodeRefs(o);
+ if (subNodeRefs != null)
+ nodeRefs.addAll(subNodeRefs);
+ }
+ return nodeRefs;
+ } else if (obj instanceof Object[]) {
+ Set nodeRefs = new LinkedHashSet<>();
+ for (Object o : ((Object[]) obj)) {
+ Collection subNodeRefs = this.extractNodeRefs(o);
+ if (subNodeRefs != null)
+ nodeRefs.addAll(subNodeRefs);
+ }
+ return nodeRefs;
+ } else {
+ return null;
+ }
+ }
+
public interface QNameBasedCallback {
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/RetryingTransactionAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/RetryingTransactionAspect.java
index d5a6233..5de69e4 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/RetryingTransactionAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/RetryingTransactionAspect.java
@@ -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());
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ThreadedAspect.java b/src/main/java/com/inteligr8/alfresco/annotations/aspect/ThreadedAspect.java
index 2521f02..a2e0f03 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/aspect/ThreadedAspect.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/aspect/ThreadedAspect.java
@@ -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 {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -53,6 +57,7 @@ public class ThreadedAspect extends AbstractMethodAspect {
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 {
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());
}
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/AlfrescoTransactionManager.java b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/AlfrescoTransactionManager.java
index f0f777f..4d8eb31 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/AlfrescoTransactionManager.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/AlfrescoTransactionManager.java
@@ -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 {
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/MqAsyncService.java b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/MqAsyncService.java
index 9bf5c21..14f8fa4 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/MqAsyncService.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/MqAsyncService.java
@@ -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, 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;
diff --git a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/ThreadPoolAsyncService.java b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/ThreadPoolAsyncService.java
index 10941a7..70421be 100644
--- a/src/main/java/com/inteligr8/alfresco/annotations/service/impl/ThreadPoolAsyncService.java
+++ b/src/main/java/com/inteligr8/alfresco/annotations/service/impl/ThreadPoolAsyncService.java
@@ -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
*/
diff --git a/src/main/resources/META-INF/aop.xml b/src/main/resources/META-INF/aop.xml
index 4b13f64..b704794 100644
--- a/src/main/resources/META-INF/aop.xml
+++ b/src/main/resources/META-INF/aop.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/log4j2.properties b/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/log4j2.properties
new file mode 100644
index 0000000..fcb4e42
--- /dev/null
+++ b/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/log4j2.properties
@@ -0,0 +1,2 @@
+logger.inteligr8-annotations.name=com.inteligr8.alfresco.annotations
+logger.inteligr8-annotations.level=info
diff --git a/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/module.properties b/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/module.properties
index 3f654aa..319aecb 100644
--- a/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/module.properties
+++ b/src/main/resources/alfresco/module/com.inteligr8.alfresco.annotations-platform-module/module.properties
@@ -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-*
diff --git a/src/test/java/com/inteligr8/alfresco/annotations/ClusterSynchronizedTest.java b/src/test/java/com/inteligr8/alfresco/annotations/JobSynchronizedTest.java
similarity index 69%
rename from src/test/java/com/inteligr8/alfresco/annotations/ClusterSynchronizedTest.java
rename to src/test/java/com/inteligr8/alfresco/annotations/JobSynchronizedTest.java
index 471bc19..0011916 100644
--- a/src/test/java/com/inteligr8/alfresco/annotations/ClusterSynchronizedTest.java
+++ b/src/test/java/com/inteligr8/alfresco/annotations/JobSynchronizedTest.java
@@ -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) {
}
diff --git a/src/test/resources/alfresco/extension/debug-log4j.properties b/src/test/resources/alfresco/extension/debug-log4j.properties
index 70daf04..82e5f94 100644
--- a/src/test/resources/alfresco/extension/debug-log4j.properties
+++ b/src/test/resources/alfresco/extension/debug-log4j.properties
@@ -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
diff --git a/src/test/resources/alfresco/extension/debug-log4j2.properties b/src/test/resources/alfresco/extension/debug-log4j2.properties
new file mode 100644
index 0000000..930a7ff
--- /dev/null
+++ b/src/test/resources/alfresco/extension/debug-log4j2.properties
@@ -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