You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/10/10 06:37:04 UTC

[15/18] syncope git commit: [SYNCOPE-956] IT using Groovy implementations

[SYNCOPE-956] IT using Groovy implementations


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/2ebcff24
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/2ebcff24
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/2ebcff24

Branch: refs/heads/master
Commit: 2ebcff24333ea7f9c437c4729d89bc952f1bd933
Parents: d5b5792
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Oct 3 12:16:30 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Oct 10 08:34:14 2017 +0200

----------------------------------------------------------------------
 .../jpa/entity/JPAImplementation.java           |  2 +
 .../validation/entity/ImplementationCheck.java  | 41 +++++++++++
 .../entity/ImplementationValidator.java         | 40 +++++++++++
 .../core/reference/DoubleValueLogicActions.java | 75 --------------------
 .../core/reference/ITImplementationLookup.java  |  4 --
 .../core/reference/PrefixItemTransformer.java   | 66 -----------------
 .../fit/core/reference/TestPullRule.java        | 40 -----------
 .../TestReconciliationFilterBuilder.java        | 35 ---------
 .../apache/syncope/fit/core/PolicyITCase.java   | 26 +++----
 .../apache/syncope/fit/core/PullTaskITCase.java | 43 +++++------
 .../syncope/fit/core/UserIssuesITCase.java      | 11 +--
 .../resources/DoubleValueLogicActions.groovy    | 73 +++++++++++++++++++
 .../test/resources/PrefixItemTransformer.groovy | 67 +++++++++++++++++
 .../src/test/resources/TestPullRule.groovy      | 40 +++++++++++
 .../resources/TestReconFilterBuilder.groovy     | 35 +++++++++
 .../src/test/resources/log4j2.xml               |  8 +++
 pom.xml                                         |  6 --
 17 files changed, 348 insertions(+), 264 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
index dfa1134..c4945fd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
@@ -28,9 +28,11 @@ import javax.persistence.Table;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.jpa.validation.entity.ImplementationCheck;
 
 @Entity
 @Table(name = JPAImplementation.TABLE)
+@ImplementationCheck
 @Cacheable
 public class JPAImplementation extends AbstractProvidedKeyEntity implements Implementation {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationCheck.java
new file mode 100644
index 0000000..a613f87
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationCheck.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = ImplementationValidator.class)
+@Documented
+public @interface ImplementationCheck {
+
+    String message() default "{org.apache.syncope.core.persistence.validation.implementation}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationValidator.java
new file mode 100644
index 0000000..095a97d
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ImplementationValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+
+public class ImplementationValidator extends AbstractValidator<ImplementationCheck, Implementation> {
+
+    @Override
+    public boolean isValid(final Implementation resource, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        if (resource.getKey() == null || !KEY_PATTERN.matcher(resource.getKey()).matches()) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidKey, "Invalid implementation key")).
+                    addPropertyNode("key").addConstraintViolation();
+            return false;
+        }
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DoubleValueLogicActions.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DoubleValueLogicActions.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DoubleValueLogicActions.java
deleted file mode 100644
index 6c79367..0000000
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DoubleValueLogicActions.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.fit.core.reference;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.patch.AttrPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.core.provisioning.api.LogicActions;
-
-/**
- * Class for integration tests: transform (by making it double) any attribute value for defined schema.
- */
-public class DoubleValueLogicActions implements LogicActions {
-
-    private static final String NAME = "makeItDouble";
-
-    @Override
-    public <A extends AnyTO> A beforeCreate(final A input) {
-        for (AttrTO attr : input.getPlainAttrs()) {
-            if (NAME.equals(attr.getSchema())) {
-                List<String> values = new ArrayList<>(attr.getValues().size());
-                for (String value : attr.getValues()) {
-                    try {
-                        values.add(String.valueOf(2 * Long.parseLong(value)));
-                    } catch (NumberFormatException e) {
-                        // ignore
-                    }
-                }
-                attr.getValues().clear();
-                attr.getValues().addAll(values);
-            }
-        }
-
-        return input;
-    }
-
-    @Override
-    public <M extends AnyPatch> M beforeUpdate(final M input) {
-        for (AttrPatch patch : input.getPlainAttrs()) {
-            if (NAME.equals(patch.getAttrTO().getSchema())) {
-                List<String> values = new ArrayList<>(patch.getAttrTO().getValues().size());
-                for (String value : patch.getAttrTO().getValues()) {
-                    try {
-                        values.add(String.valueOf(2 * Long.parseLong(value)));
-                    } catch (NumberFormatException e) {
-                        // ignore
-                    }
-                }
-                patch.getAttrTO().getValues().clear();
-                patch.getAttrTO().getValues().addAll(values);
-            }
-        }
-
-        return input;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index e4d94d0..d4467e8 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -146,7 +146,6 @@ public class ITImplementationLookup implements ImplementationLookup {
             put(ImplementationType.PASSWORD_RULE, classNames);
 
             classNames = new HashSet<>();
-            classNames.add(PrefixItemTransformer.class.getName());
             put(ImplementationType.ITEM_TRANSFORMER, classNames);
 
             classNames = new HashSet<>();
@@ -154,11 +153,9 @@ public class ITImplementationLookup implements ImplementationLookup {
             put(ImplementationType.TASKJOB_DELEGATE, classNames);
 
             classNames = new HashSet<>();
-            classNames.add(TestReconciliationFilterBuilder.class.getName());
             put(ImplementationType.RECON_FILTER_BUILDER, classNames);
 
             classNames = new HashSet<>();
-            classNames.add(DoubleValueLogicActions.class.getName());
             put(ImplementationType.LOGIC_ACTIONS, classNames);
 
             classNames = new HashSet<>();
@@ -179,7 +176,6 @@ public class ITImplementationLookup implements ImplementationLookup {
             put(ImplementationType.PUSH_ACTIONS, classNames);
 
             classNames = new HashSet<>();
-            classNames.add(TestPullRule.class.getName());
             put(ImplementationType.PULL_CORRELATION_RULE, classNames);
 
             classNames = new HashSet<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
deleted file mode 100644
index 07f7968..0000000
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.fit.core.reference;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.to.EntityTO;
-import org.apache.syncope.core.persistence.api.entity.Entity;
-import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.resource.Item;
-import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
-
-public class PrefixItemTransformer implements ItemTransformer {
-
-    public static final String PREFIX = "PREFIX_";
-
-    @Override
-    public List<PlainAttrValue> beforePropagation(
-            final Item item,
-            final Entity entity,
-            final List<PlainAttrValue> values) {
-
-        if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
-            return values;
-        } else {
-            String value = values.get(0).getStringValue();
-            values.get(0).setStringValue(PREFIX + value);
-
-            return values;
-        }
-    }
-
-    @Override
-    public List<Object> beforePull(
-            final Item item,
-            final EntityTO entityTO,
-            final List<Object> values) {
-
-        if (values == null || values.isEmpty() || values.get(0) == null) {
-            return values;
-        } else {
-            List<Object> newValues = new ArrayList<>(values);
-            newValues.set(0, StringUtils.substringAfter(values.get(0).toString(), PREFIX));
-
-            return newValues;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullRule.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullRule.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullRule.java
deleted file mode 100644
index 71d36a7..0000000
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullRule.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.fit.core.reference;
-
-import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
-
-/**
- * Test pull rule relying on <tt>email</tt> attribute value.
- */
-public class TestPullRule implements PullCorrelationRule {
-
-    @Override
-    public SearchCond getSearchCond(final ConnectorObject connObj) {
-        AttributeCond cond = new AttributeCond();
-        cond.setSchema("email");
-        cond.setType(AttributeCond.Type.EQ);
-        cond.setExpression(connObj.getName().getNameValue());
-
-        return SearchCond.getLeafCond(cond);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
deleted file mode 100644
index 931b183..0000000
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.fit.core.reference;
-
-import org.identityconnectors.framework.common.objects.AttributeBuilder;
-import org.identityconnectors.framework.common.objects.filter.Filter;
-import org.identityconnectors.framework.common.objects.filter.FilterBuilder;
-import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
-
-public class TestReconciliationFilterBuilder implements ReconFilterBuilder {
-
-    private static final Filter EQUALS = FilterBuilder.equalTo(AttributeBuilder.build("SURNAME", "Rossi"));
-
-    @Override
-    public Filter build() {
-        return EQUALS;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
index 51b49ff..052cc3d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -25,9 +25,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.List;
 import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
@@ -46,22 +49,22 @@ import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.fit.AbstractITCase;
-import org.apache.syncope.fit.core.reference.TestPullRule;
 import org.junit.jupiter.api.Test;
 
 public class PolicyITCase extends AbstractITCase {
 
-    private PullPolicyTO buildPullPolicyTO() {
+    private PullPolicyTO buildPullPolicyTO() throws IOException {
         ImplementationTO corrRule = null;
         try {
-            corrRule = implementationService.read(TestPullRule.class.getSimpleName());
+            corrRule = implementationService.read("TestPullRule");
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 corrRule = new ImplementationTO();
-                corrRule.setKey(TestPullRule.class.getSimpleName());
-                corrRule.setEngine(ImplementationEngine.JAVA);
+                corrRule.setKey("TestPullRule");
+                corrRule.setEngine(ImplementationEngine.GROOVY);
                 corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
-                corrRule.setBody(TestPullRule.class.getName());
+                corrRule.setBody(IOUtils.toString(
+                        getClass().getResourceAsStream("/TestPullRule.groovy"), StandardCharsets.UTF_8));
                 Response response = implementationService.create(corrRule);
                 corrRule = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
                 assertNotNull(corrRule);
@@ -127,14 +130,13 @@ public class PolicyITCase extends AbstractITCase {
     }
 
     @Test
-    public void create() {
+    public void create() throws IOException {
         PullPolicyTO policy = buildPullPolicyTO();
 
         PullPolicyTO policyTO = createPolicy(policy);
 
         assertNotNull(policyTO);
-        assertEquals(TestPullRule.class.getSimpleName(),
-                policyTO.getSpecification().getCorrelationRules().get(AnyTypeKind.USER.name()));
+        assertEquals("TestPullRule", policyTO.getSpecification().getCorrelationRules().get(AnyTypeKind.USER.name()));
     }
 
     @Test
@@ -167,7 +169,7 @@ public class PolicyITCase extends AbstractITCase {
     }
 
     @Test
-    public void delete() {
+    public void delete() throws IOException {
         PullPolicyTO policy = buildPullPolicyTO();
 
         PullPolicyTO policyTO = createPolicy(policy);
@@ -185,8 +187,8 @@ public class PolicyITCase extends AbstractITCase {
 
     @Test
     public void getPullCorrelationRuleJavaClasses() {
-        assertEquals(1, syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PULL_CORRELATION_RULE).get().getClasses().size());
+        assertTrue(syncopeService.platform().
+                getJavaImplInfo(ImplementationType.PULL_CORRELATION_RULE).get().getClasses().isEmpty());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index 5d67ece..848b97c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -30,6 +30,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Locale;
@@ -85,10 +86,7 @@ import org.apache.syncope.core.provisioning.java.pushpull.DBPasswordPullActions;
 import org.apache.syncope.core.provisioning.java.pushpull.LDAPPasswordPullActions;
 import org.apache.syncope.core.spring.security.Encryptor;
 import org.apache.syncope.fit.FlowableDetector;
-import org.apache.syncope.fit.core.reference.PrefixItemTransformer;
-import org.apache.syncope.fit.core.reference.TestReconciliationFilterBuilder;
 import org.apache.syncope.fit.core.reference.TestPullActions;
-import org.apache.syncope.fit.core.reference.TestPullRule;
 import org.identityconnectors.framework.common.objects.Name;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -418,7 +416,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
     }
 
     @Test
-    public void reconcileFromScriptedSQL() {
+    public void reconcileFromScriptedSQL() throws IOException {
         // 0. reset sync token and set MappingItemTransformer
         ResourceTO resource = resourceService.read(RESOURCE_NAME_DBSCRIPTED);
         ResourceTO originalResource = SerializationUtils.clone(resource);
@@ -429,11 +427,14 @@ public class PullTaskITCase extends AbstractTaskITCase {
                 filter(object -> "location".equals(object.getIntAttrName())).findFirst().get();
         assertNotNull(mappingItem);
 
+        final String prefix = "PREFIX_";
+
         ImplementationTO transformer = new ImplementationTO();
-        transformer.setKey(PrefixItemTransformer.class.getSimpleName());
-        transformer.setEngine(ImplementationEngine.JAVA);
+        transformer.setKey("PrefixItemTransformer");
+        transformer.setEngine(ImplementationEngine.GROOVY);
         transformer.setType(ImplementationType.ITEM_TRANSFORMER);
-        transformer.setBody(PrefixItemTransformer.class.getName());
+        transformer.setBody(IOUtils.toString(
+                getClass().getResourceAsStream("/PrefixItemTransformer.groovy"), StandardCharsets.UTF_8));
         Response response = implementationService.create(transformer);
         transformer = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
         assertNotNull(transformer);
@@ -455,7 +456,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
             // 1. create printer on external resource
             AnyObjectTO anyObjectTO = AnyObjectITCase.getSampleTO("pull");
             String originalLocation = anyObjectTO.getPlainAttr("location").get().getValues().get(0);
-            assertFalse(originalLocation.startsWith(PrefixItemTransformer.PREFIX));
+            assertFalse(originalLocation.startsWith(prefix));
 
             anyObjectTO = createAnyObject(anyObjectTO).getEntity();
             assertNotNull(anyObjectTO);
@@ -464,10 +465,8 @@ public class PullTaskITCase extends AbstractTaskITCase {
             // (location starts with given prefix on external resource)
             ConnObjectTO connObjectTO = resourceService.
                     readConnObject(RESOURCE_NAME_DBSCRIPTED, anyObjectTO.getType(), anyObjectTO.getKey());
-            assertFalse(anyObjectTO.getPlainAttr("location").get().getValues().get(0).
-                    startsWith(PrefixItemTransformer.PREFIX));
-            assertTrue(connObjectTO.getAttr("LOCATION").get().getValues().get(0).
-                    startsWith(PrefixItemTransformer.PREFIX));
+            assertFalse(anyObjectTO.getPlainAttr("location").get().getValues().get(0).startsWith(prefix));
+            assertTrue(connObjectTO.getAttr("LOCATION").get().getValues().get(0).startsWith(prefix));
 
             // 3. unlink any existing printer and delete from Syncope (printer is now only on external resource)
             PagedResult<AnyObjectTO> matchingPrinters = anyObjectService.search(
@@ -505,7 +504,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
     }
 
     @Test
-    public void filteredReconciliation() {
+    public void filteredReconciliation() throws IOException {
         String user1OnTestPull = UUID.randomUUID().toString();
         String user2OnTestPull = UUID.randomUUID().toString();
 
@@ -521,10 +520,11 @@ public class PullTaskITCase extends AbstractTaskITCase {
 
             // 2. create new pull task for test-db, with reconciliation filter (surname 'Rossi') 
             ImplementationTO reconFilterBuilder = new ImplementationTO();
-            reconFilterBuilder.setKey(TestReconciliationFilterBuilder.class.getSimpleName());
-            reconFilterBuilder.setEngine(ImplementationEngine.JAVA);
+            reconFilterBuilder.setKey("TestReconFilterBuilder");
+            reconFilterBuilder.setEngine(ImplementationEngine.GROOVY);
             reconFilterBuilder.setType(ImplementationType.RECON_FILTER_BUILDER);
-            reconFilterBuilder.setBody(TestReconciliationFilterBuilder.class.getName());
+            reconFilterBuilder.setBody(IOUtils.toString(
+                    getClass().getResourceAsStream("/TestReconFilterBuilder.groovy"), StandardCharsets.UTF_8));
             Response response = implementationService.create(reconFilterBuilder);
             reconFilterBuilder = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
             assertNotNull(reconFilterBuilder);
@@ -749,20 +749,21 @@ public class PullTaskITCase extends AbstractTaskITCase {
     }
 
     @Test
-    public void issueSYNCOPE258() {
+    public void issueSYNCOPE258() throws IOException {
         // -----------------------------
         // Add a custom correlation rule
         // -----------------------------
         ImplementationTO corrRule = null;
         try {
-            corrRule = implementationService.read(TestPullRule.class.getSimpleName());
+            corrRule = implementationService.read("TestPullRule");
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 corrRule = new ImplementationTO();
-                corrRule.setKey(TestPullRule.class.getSimpleName());
-                corrRule.setEngine(ImplementationEngine.JAVA);
+                corrRule.setKey("TestPullRule");
+                corrRule.setEngine(ImplementationEngine.GROOVY);
                 corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
-                corrRule.setBody(TestPullRule.class.getName());
+                corrRule.setBody(IOUtils.toString(
+                        getClass().getResourceAsStream("/TestPullRule.groovy"), StandardCharsets.UTF_8));
                 Response response = implementationService.create(corrRule);
                 corrRule = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
                 assertNotNull(corrRule);

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
index 91072d1..2c28906 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.Collection;
 import java.util.Collections;
@@ -78,7 +79,6 @@ import org.apache.syncope.core.provisioning.java.propagation.DBPasswordPropagati
 import org.apache.syncope.core.provisioning.java.propagation.LDAPPasswordPropagationActions;
 import org.apache.syncope.core.spring.security.Encryptor;
 import org.apache.syncope.fit.AbstractITCase;
-import org.apache.syncope.fit.core.reference.DoubleValueLogicActions;
 import org.identityconnectors.framework.common.objects.Name;
 import org.identityconnectors.framework.common.objects.OperationalAttributes;
 import org.junit.jupiter.api.Test;
@@ -798,12 +798,13 @@ public class UserIssuesITCase extends AbstractITCase {
     }
 
     @Test
-    public void issueSYNCOPE420() {
+    public void issueSYNCOPE420() throws IOException {
         ImplementationTO logicActions = new ImplementationTO();
-        logicActions.setKey(DoubleValueLogicActions.class.getSimpleName());
-        logicActions.setEngine(ImplementationEngine.JAVA);
+        logicActions.setKey("DoubleValueLogicActions");
+        logicActions.setEngine(ImplementationEngine.GROOVY);
         logicActions.setType(ImplementationType.LOGIC_ACTIONS);
-        logicActions.setBody(DoubleValueLogicActions.class.getName());
+        logicActions.setBody(org.apache.commons.io.IOUtils.toString(
+                getClass().getResourceAsStream("/DoubleValueLogicActions.groovy"), StandardCharsets.UTF_8));
         Response response = implementationService.create(logicActions);
         logicActions = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
         assertNotNull(logicActions);

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/resources/DoubleValueLogicActions.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/DoubleValueLogicActions.groovy b/fit/core-reference/src/test/resources/DoubleValueLogicActions.groovy
new file mode 100644
index 0000000..a7bc87d
--- /dev/null
+++ b/fit/core-reference/src/test/resources/DoubleValueLogicActions.groovy
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.common.lib.patch.AnyPatch
+import org.apache.syncope.common.lib.patch.AttrPatch
+import org.apache.syncope.common.lib.to.AnyTO
+import org.apache.syncope.common.lib.to.AttrTO
+import org.apache.syncope.core.provisioning.api.LogicActions
+
+/**
+ * Class for integration tests: transform (by making it double) any attribute value for defined schema.
+ */
+@CompileStatic
+class DoubleValueLogicActions implements LogicActions {
+  
+  private static final String NAME = "makeItDouble";
+
+  @Override
+  <A extends AnyTO> A beforeCreate(final A input) {
+    for (AttrTO attr : input.getPlainAttrs()) {
+      if (NAME.equals(attr.getSchema())) {
+        List<String> values = new ArrayList<String>(attr.getValues().size());
+        for (String value : attr.getValues()) {
+          try {
+            values.add(String.valueOf(2 * Long.parseLong(value)));
+          } catch (NumberFormatException e) {
+            // ignore
+          }
+        }
+        attr.getValues().clear();
+        attr.getValues().addAll(values);
+      }
+    }
+
+    return input;
+  }
+
+  @Override
+  <M extends AnyPatch> M beforeUpdate(final M input) {
+    for (AttrPatch patch : input.getPlainAttrs()) {
+      if (NAME.equals(patch.getAttrTO().getSchema())) {
+        List<String> values = new ArrayList<String>(patch.getAttrTO().getValues().size());
+        for (String value : patch.getAttrTO().getValues()) {
+          try {
+            values.add(String.valueOf(2 * Long.parseLong(value)));
+          } catch (NumberFormatException e) {
+            // ignore
+          }
+        }
+        patch.getAttrTO().getValues().clear();
+        patch.getAttrTO().getValues().addAll(values);
+      }
+    }
+
+    return input;
+  }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/resources/PrefixItemTransformer.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/PrefixItemTransformer.groovy b/fit/core-reference/src/test/resources/PrefixItemTransformer.groovy
new file mode 100644
index 0000000..c26aef1
--- /dev/null
+++ b/fit/core-reference/src/test/resources/PrefixItemTransformer.groovy
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import java.util.ArrayList;
+import groovy.transform.CompileStatic
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
+
+@CompileStatic
+class PrefixItemTransformer implements ItemTransformer {
+	
+  public static String PREFIX = "PREFIX_";
+
+  @Override
+  List<PlainAttrValue> beforePropagation(
+    Item item,
+    Entity entity,
+    List<PlainAttrValue> values) {
+
+    if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
+      return values;
+    } else {
+      String value = values.get(0).getStringValue();
+      values.get(0).setStringValue(PREFIX + value);
+
+      return values;
+    }
+  }
+
+  @Override
+  List<Object> beforePull(
+    Item item,
+    EntityTO entityTO,
+    List<Object> values) {
+
+    if (values == null || values.isEmpty() || values.get(0) == null) {
+      return values;
+    } else {
+      List<Object> newValues = new ArrayList<>(values);
+      newValues.set(0, StringUtils.substringAfter(values.get(0).toString(), PREFIX));
+
+      return newValues;
+    }
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/resources/TestPullRule.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/TestPullRule.groovy b/fit/core-reference/src/test/resources/TestPullRule.groovy
new file mode 100644
index 0000000..3203c7b
--- /dev/null
+++ b/fit/core-reference/src/test/resources/TestPullRule.groovy
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+
+/**
+ * Test pull rule relying on <tt>email</tt> attribute value.
+ */
+@CompileStatic
+class TestPullRule implements PullCorrelationRule {
+
+  @Override
+  SearchCond getSearchCond(final ConnectorObject connObj) {
+    AttributeCond cond = new AttributeCond();
+    cond.setSchema("email");
+    cond.setType(AttributeCond.Type.EQ);
+    cond.setExpression(connObj.getName().getNameValue());
+
+    return SearchCond.getLeafCond(cond);
+  }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/resources/TestReconFilterBuilder.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/TestReconFilterBuilder.groovy b/fit/core-reference/src/test/resources/TestReconFilterBuilder.groovy
new file mode 100644
index 0000000..b7ebe49
--- /dev/null
+++ b/fit/core-reference/src/test/resources/TestReconFilterBuilder.groovy
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.identityconnectors.framework.common.objects.filter.Filter;
+import org.identityconnectors.framework.common.objects.filter.FilterBuilder;
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
+
+@CompileStatic
+class TestReconFilterBuilder implements ReconFilterBuilder {
+
+  private static final Filter EQUALS = FilterBuilder.equalTo(AttributeBuilder.build("SURNAME", "Rossi"));
+
+  @Override
+  Filter build() {
+    return EQUALS;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/fit/core-reference/src/test/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/log4j2.xml b/fit/core-reference/src/test/resources/log4j2.xml
index cfb3a62..a3fe0d6 100644
--- a/fit/core-reference/src/test/resources/log4j2.xml
+++ b/fit/core-reference/src/test/resources/log4j2.xml
@@ -33,6 +33,14 @@ under the License.
   </appenders>
 
   <loggers>
+    <asyncLogger name="org.apache.cxf" additivity="false" level="ERROR">
+      <appender-ref ref="main"/>
+    </asyncLogger>
+
+    <asyncLogger name="org.springframework" additivity="false" level="ERROR">
+      <appender-ref ref="main"/>
+    </asyncLogger>
+
     <asyncLogger name="org.apache.syncope.fit" additivity="false" level="DEBUG">
       <appender-ref ref="main"/>
     </asyncLogger>

http://git-wip-us.apache.org/repos/asf/syncope/blob/2ebcff24/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b5c7512..edd7463 100644
--- a/pom.xml
+++ b/pom.xml
@@ -736,12 +736,6 @@ under the License.
         <groupId>org.apache.openjpa</groupId>
         <artifactId>openjpa-jdbc</artifactId>
         <version>${openjpa.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-          </exclusion>
-        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.apache.openjpa</groupId>