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 2015/06/11 16:17:36 UTC

[46/70] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
new file mode 100644
index 0000000..8747631
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
@@ -0,0 +1,131 @@
+/*
+ * 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.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeClassDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO> {
+
+    @Autowired
+    private AnyTypeClassDataBinder binder;
+
+    @Autowired
+    private AnyTypeClassDAO anyTypeDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_READ + "')")
+    public AnyTypeClassTO read(final String key) {
+        AnyTypeClass anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getAnyTypeClassTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_LIST + "')")
+    public List<AnyTypeClassTO> list() {
+        return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() {
+
+            @Override
+            public AnyTypeClassTO transform(final AnyTypeClass input) {
+                return binder.getAnyTypeClassTO(input);
+            }
+        }, new ArrayList<AnyTypeClassTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_CREATE + "')")
+    public AnyTypeClassTO create(final AnyTypeClassTO anyTypeTO) {
+        return binder.getAnyTypeClassTO(anyTypeDAO.save(binder.create(anyTypeTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_UPDATE + "')")
+    public AnyTypeClassTO update(final AnyTypeClassTO anyTypeTO) {
+        AnyTypeClass anyType = anyTypeDAO.find(anyTypeTO.getKey());
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(anyTypeTO.getKey()));
+        }
+
+        binder.update(anyType, anyTypeTO);
+        anyType = anyTypeDAO.save(anyType);
+
+        return binder.getAnyTypeClassTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_DELETE + "')")
+    public AnyTypeClassTO delete(final String key) {
+        AnyTypeClass anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyType);
+        anyTypeDAO.delete(key);
+        return deleted;
+    }
+
+    @Override
+    protected AnyTypeClassTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof Long) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof AnyTypeClassTO) {
+                    key = ((AnyTypeClassTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getAnyTypeClassTO(anyTypeDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
new file mode 100644
index 0000000..93af622
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
@@ -0,0 +1,131 @@
+/*
+ * 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.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> {
+
+    @Autowired
+    private AnyTypeDataBinder binder;
+
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_READ + "')")
+    public AnyTypeTO read(final String key) {
+        AnyType anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getAnyTypeTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_LIST + "')")
+    public List<AnyTypeTO> list() {
+        return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyType, AnyTypeTO>() {
+
+            @Override
+            public AnyTypeTO transform(final AnyType input) {
+                return binder.getAnyTypeTO(input);
+            }
+        }, new ArrayList<AnyTypeTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_CREATE + "')")
+    public AnyTypeTO create(final AnyTypeTO anyTypeTO) {
+        return binder.getAnyTypeTO(anyTypeDAO.save(binder.create(anyTypeTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_UPDATE + "')")
+    public AnyTypeTO update(final AnyTypeTO anyTypeTO) {
+        AnyType anyType = anyTypeDAO.find(anyTypeTO.getKey());
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(anyTypeTO.getKey()));
+        }
+
+        binder.update(anyType, anyTypeTO);
+        anyType = anyTypeDAO.save(anyType);
+
+        return binder.getAnyTypeTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_DELETE + "')")
+    public AnyTypeTO delete(final String key) {
+        AnyType anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        AnyTypeTO deleted = binder.getAnyTypeTO(anyType);
+        anyTypeDAO.delete(key);
+        return deleted;
+    }
+
+    @Override
+    protected AnyTypeTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof Long) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof AnyTypeTO) {
+                    key = ((AnyTypeTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getAnyTypeTO(anyTypeDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
index 968a34c..77ff7b5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
@@ -34,9 +34,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 @Aspect
 public class LogicInvocationHandler {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(LogicInvocationHandler.class);
 
     @Autowired
@@ -47,16 +44,16 @@ public class LogicInvocationHandler {
 
     @Around("execution(* org.apache.syncope.core.logic.AbstractLogic+.*(..))")
     public Object around(final ProceedingJoinPoint joinPoint) throws Throwable {
-        final Class<?> clazz = joinPoint.getTarget().getClass();
+        Class<?> clazz = joinPoint.getTarget().getClass();
 
-        final Object[] input = joinPoint.getArgs();
+        Object[] input = joinPoint.getArgs();
 
-        final String category = clazz.getSimpleName();
+        String category = clazz.getSimpleName();
 
-        final MethodSignature ms = (MethodSignature) joinPoint.getSignature();
+        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
         Method method = ms.getMethod();
 
-        final String event = joinPoint.getSignature().getName();
+        String event = joinPoint.getSignature().getName();
 
         AuditElements.Result result = null;
         Object output = null;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 073150b..863af12 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -217,7 +217,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
                 connector.getOperationOptions(attrUtils.getMappingItems(provision, MappingPurpose.BOTH)));
         if (connectorObject == null) {
             throw new NotFoundException("Object " + connObjectKeyValue + " with class " + provision.getObjectClass()
-                    + "not found on resource " + resourceKey);
+                    + " not found on resource " + resourceKey);
         }
 
         final Set<Attribute> attributes = connectorObject.getAttributes();

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 37acf19..4ecab47 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -50,12 +50,12 @@ import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
 import org.apache.syncope.core.misc.security.UnauthorizedException;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.provisioning.api.AnyTransformer;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
@@ -205,7 +205,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
 
         Map.Entry<Long, List<PropagationStatus>> created = provisioningManager.create(actual, storePassword);
 
-        final UserTO savedTO = binder.getUserTO(created.getKey());
+        UserTO savedTO = binder.getUserTO(created.getKey());
         savedTO.getPropagationStatusTOs().addAll(created.getValue());
         return savedTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
index 106ed36..6a8289a 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
@@ -57,6 +57,7 @@ import org.quartz.impl.JobDetailImpl;
 import org.quartz.impl.triggers.CronTriggerImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@@ -126,6 +127,30 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
         }
     }
 
+    private Job createSpringBean(final Class<?> jobClass) {
+        Job jobInstance = null;
+        for (int i = 0; i < 5 && jobInstance == null; i++) {
+            LOG.debug("{} attempt to create Spring bean for {}", i, jobClass);
+            try {
+                jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
+                        createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                LOG.debug("{} attempt to create Spring bean for {} succeeded", i, jobClass);
+            } catch (BeanCreationException e) {
+                LOG.error("Could not create Spring bean for {}", jobClass, e);
+                try {
+                    Thread.sleep(1000);
+                } catch (final InterruptedException ex) {
+                    // ignore
+                }
+            }
+        }
+        if (jobInstance == null) {
+            throw new NotFoundException("Spring bean for " + jobClass);
+        }
+
+        return jobInstance;
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public void registerJob(final Task task, final String jobClassName, final String cronExpression)
@@ -137,8 +162,8 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
         } else if (PushJob.class.equals(jobClass)) {
             jobClass = PushJobImpl.class;
         }
-        Job jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
-                createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+
+        Job jobInstance = createSpringBean(jobClass);
         if (jobInstance instanceof TaskJob) {
             ((TaskJob) jobInstance).setTaskId(task.getKey());
         }
@@ -151,10 +176,8 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
                 try {
                     Class<?> actionsClass = Class.forName(className);
 
-                    final SyncActions syncActions =
-                            (SyncActions) ApplicationContextProvider.getBeanFactory().
+                    SyncActions syncActions = (SyncActions) ApplicationContextProvider.getBeanFactory().
                             createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-
                     actions.add(syncActions);
                 } catch (Exception e) {
                     LOG.info("Class '{}' not found", className, e);
@@ -182,8 +205,7 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
 
     @Override
     public void registerJob(final Report report) throws SchedulerException, ParseException {
-        Job jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
-                createBean(ReportJob.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+        Job jobInstance = createSpringBean(ReportJob.class);
         ((ReportJob) jobInstance).setReportKey(report.getKey());
 
         registerJob(JobNamer.getJobName(report), jobInstance, report.getCronExpression());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index b4087a7..b05c4e6 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -29,6 +29,7 @@ import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -38,6 +39,8 @@ import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.misc.DataFormat;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.URelationship;
+import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -62,6 +65,9 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     @Autowired
     private GroupDataBinder groupDataBinder;
 
+    @Autowired
+    private AnyObjectDataBinder anyObjectDataBinder;
+
     private List<User> getPagedUsers(final int page) {
         List<User> result;
 
@@ -264,14 +270,39 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
 
             doExtractAttributes(handler, userTO, conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs());
 
+            if (conf.getFeatures().contains(Feature.relationships)) {
+                handler.startElement("", "", "relationships", null);
+
+                for (RelationshipTO rel : userTO.getRelationships()) {
+                    atts.clear();
+
+                    atts.addAttribute("", "", "anyObjectKey",
+                            ReportXMLConst.XSD_LONG, String.valueOf(rel.getRightKey()));
+                    handler.startElement("", "", "relationship", atts);
+
+                    if (conf.getFeatures().contains(Feature.resources)) {
+                        URelationship actualRel = user.getRelationship(rel.getRightKey());
+                        if (actualRel == null) {
+                            LOG.warn("Unexpected: cannot find relationship for any object {} for user {}",
+                                    rel.getRightKey(), user);
+                        } else {
+                            doExtractResources(handler, anyObjectDataBinder.getAnyObjectTO(actualRel.getRightEnd()));
+                        }
+                    }
+
+                    handler.endElement("", "", "relationship");
+                }
+
+                handler.endElement("", "", "relationships");
+            }
             if (conf.getFeatures().contains(Feature.memberships)) {
                 handler.startElement("", "", "memberships", null);
 
                 for (MembershipTO memb : userTO.getMemberships()) {
                     atts.clear();
 
-                    atts.addAttribute("", "", "id", ReportXMLConst.XSD_LONG, String.valueOf(memb.getKey()));
-                    atts.addAttribute("", "", "groupId", ReportXMLConst.XSD_LONG, String.valueOf(memb.getRightKey()));
+                    atts.addAttribute("", "", "groupKey",
+                            ReportXMLConst.XSD_LONG, String.valueOf(memb.getRightKey()));
                     atts.addAttribute("", "", "groupName", ReportXMLConst.XSD_STRING, String.
                             valueOf(memb.getGroupName()));
                     handler.startElement("", "", "membership", atts);
@@ -279,8 +310,8 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
                     if (conf.getFeatures().contains(Feature.resources)) {
                         UMembership actualMemb = user.getMembership(memb.getRightKey());
                         if (actualMemb == null) {
-                            LOG.warn("Unexpected: cannot find membership for group {} for user {}", memb.getRightKey(),
-                                    user);
+                            LOG.warn("Unexpected: cannot find membership for group {} for user {}",
+                                    memb.getRightKey(), user);
                         } else {
                             doExtractResources(handler, groupDataBinder.getGroupTO(actualMemb.getRightEnd()));
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
index 279ef77..766c5cf 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
@@ -25,23 +25,21 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PasswordPolicySpec;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
@@ -54,24 +52,13 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.task.SyncTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
 import org.apache.syncope.core.misc.security.Encryptor;
-import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.task.AnyTemplate;
 import org.identityconnectors.common.Base64;
@@ -79,12 +66,9 @@ import org.identityconnectors.common.security.GuardedByteArray;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.identityconnectors.framework.common.objects.OperationOptions;
-import org.identityconnectors.framework.common.objects.Uid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -100,9 +84,6 @@ public class ConnObjectUtils {
     private UserDAO userDAO;
 
     @Autowired
-    private AnyObjectDAO anyObjectDAO;
-
-    @Autowired
     private GroupDAO groupDAO;
 
     @Autowired
@@ -114,18 +95,9 @@ public class ConnObjectUtils {
     @Autowired
     private PasswordGenerator pwdGen;
 
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
     private final Encryptor encryptor = Encryptor.getInstance();
 
     /**
-     * Virtual attribute cache.
-     */
-    @Autowired
-    private VirAttrCache virAttrCache;
-
-    /**
      * Build a UserTO / GroupTO / AnyObjectTO out of connector object attributes and schema mapping.
      *
      * @param obj connector object
@@ -213,6 +185,8 @@ public class ConnObjectUtils {
             return (T) AnyOperations.diff(((UserTO) updated), ((UserTO) original), true);
         } else if (AnyTypeKind.GROUP == anyUtils.getAnyTypeKind()) {
             return (T) AnyOperations.diff(((GroupTO) updated), ((GroupTO) original), true);
+        } else if (AnyTypeKind.ANY_OBJECT == anyUtils.getAnyTypeKind()) {
+            return (T) AnyOperations.diff(((AnyObjectTO) updated), ((AnyObjectTO) original), true);
         }
 
         return null;
@@ -348,12 +322,14 @@ public class ConnObjectUtils {
         AnyTemplate anyTypeTemplate = syncTask.getTemplate(provision.getAnyType());
         if (anyTypeTemplate != null) {
             AnyTO template = anyTypeTemplate.get();
+            fillFromTemplate(anyTO, template);
 
-            if (template.getRealm() != null) {
-                anyTO.setRealm(template.getRealm());
-            }
-
-            if (template instanceof UserTO) {
+            if (template instanceof AnyObjectTO) {
+                fillRelationshipsFromTemplate(((AnyObjectTO) anyTO).getRelationshipMap(),
+                        ((AnyObjectTO) anyTO).getRelationships(), ((AnyObjectTO) template).getRelationships());
+                fillMembershipsFromTemplate(((AnyObjectTO) anyTO).getMembershipMap(),
+                        ((AnyObjectTO) anyTO).getMemberships(), ((AnyObjectTO) template).getMemberships());
+            } else if (template instanceof UserTO) {
                 if (StringUtils.isNotBlank(((UserTO) template).getUsername())) {
                     String evaluated = JexlUtils.evaluate(((UserTO) template).getUsername(), anyTO);
                     if (StringUtils.isNotBlank(evaluated)) {
@@ -367,8 +343,12 @@ public class ConnObjectUtils {
                         ((UserTO) anyTO).setPassword(evaluated);
                     }
                 }
-            }
-            if (template instanceof GroupTO) {
+
+                fillRelationshipsFromTemplate(((UserTO) anyTO).getRelationshipMap(),
+                        ((UserTO) anyTO).getRelationships(), ((UserTO) template).getRelationships());
+                fillMembershipsFromTemplate(((UserTO) anyTO).getMembershipMap(),
+                        ((UserTO) anyTO).getMemberships(), ((UserTO) template).getMemberships());
+            } else if (template instanceof GroupTO) {
                 if (StringUtils.isNotBlank(((GroupTO) template).getName())) {
                     String evaluated = JexlUtils.evaluate(((GroupTO) template).getName(), anyTO);
                     if (StringUtils.isNotBlank(evaluated)) {
@@ -389,12 +369,6 @@ public class ConnObjectUtils {
                     }
                 }
             }
-
-            fillFromTemplate(anyTO, template);
-
-            for (String resource : template.getResources()) {
-                anyTO.getResources().add(resource);
-            }
         }
 
         return anyTO;
@@ -467,171 +441,34 @@ public class ConnObjectUtils {
         return connObjectTO;
     }
 
-    /**
-     * Query connected external resources for values to populated virtual attributes associated with the given owner.
-     *
-     * @param any any object
-     */
-    public void retrieveVirAttrValues(final Any<?, ?, ?> any) {
-        ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext();
-        ConnectorFactory connFactory = context.getBean(ConnectorFactory.class);
-
-        IntMappingType type = any.getType().getKind() == AnyTypeKind.USER
-                ? IntMappingType.UserVirtualSchema
-                : any.getType().getKind() == AnyTypeKind.GROUP
-                        ? IntMappingType.GroupVirtualSchema
-                        : IntMappingType.AnyVirtualSchema;
-
-        Map<String, ConnectorObject> resources = new HashMap<>();
-
-        // -----------------------
-        // Retrieve virtual attribute values if and only if they have not been retrieved yet
-        // -----------------------
-        for (VirAttr<?> virAttr : any.getVirAttrs()) {
-            // reset value set
-            if (virAttr.getValues().isEmpty()) {
-                retrieveVirAttrValue(any, virAttr, type, resources, connFactory);
-            }
-        }
-        // -----------------------
-    }
-
-    private void retrieveVirAttrValue(
-            final Any<?, ?, ?> any,
-            final VirAttr<?> virAttr,
-            final IntMappingType type,
-            final Map<String, ConnectorObject> externalResources,
-            final ConnectorFactory connFactory) {
-
-        String schemaName = virAttr.getSchema().getKey();
-        VirAttrCacheValue virAttrCacheValue = virAttrCache.get(any.getType().getKey(), any.getKey(), schemaName);
-
-        LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
-
-        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
-            // cached ...
-            LOG.debug("Values found in cache {}", virAttrCacheValue);
-            virAttr.getValues().clear();
-            virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
-        } else {
-            // not cached ...
-            LOG.debug("Need one or more remote connections");
-
-            VirAttrCacheValue toBeCached = new VirAttrCacheValue();
-
-            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-            Collection<ExternalResource> targetResources = getTargetResources(virAttr, type, anyUtils, any.getType());
-
-            for (ExternalResource resource : targetResources) {
-                Provision provision = resource.getProvision(any.getType());
-                LOG.debug("Search values into {},{}", resource, provision);
-
-                if (provision != null) {
-                    try {
-                        List<MappingItem> mappings = anyUtils.getMappingItems(provision, MappingPurpose.BOTH);
-
-                        ConnectorObject connectorObject;
-                        if (externalResources.containsKey(resource.getKey())) {
-                            connectorObject = externalResources.get(resource.getKey());
-                        } else {
-                            LOG.debug("Perform connection to {}", resource.getKey());
-                            String connObjectKey = anyUtils.getConnObjectKeyItem(provision) == null
-                                    ? null
-                                    : MappingUtils.getConnObjectKeyValue(any, provision);
-
-                            if (StringUtils.isBlank(connObjectKey)) {
-                                throw new IllegalArgumentException("No ConnObjectKey found for " + resource.getKey());
-                            }
-
-                            Connector connector = connFactory.getConnector(resource);
-
-                            OperationOptions oo =
-                                    connector.getOperationOptions(MappingUtils.getMatchingMappingItems(mappings, type));
-
-                            connectorObject =
-                                    connector.getObject(provision.getObjectClass(), new Uid(connObjectKey), oo);
-                            externalResources.put(resource.getKey(), connectorObject);
-                        }
-
-                        if (connectorObject != null) {
-                            // ask for searched virtual attribute value
-                            Collection<MappingItem> virAttrMappings =
-                                    MappingUtils.getMatchingMappingItems(mappings, schemaName, type);
-
-                            // the same virtual attribute could be mapped with one or more external attribute 
-                            for (MappingItem mapping : virAttrMappings) {
-                                Attribute attribute = connectorObject.getAttributeByName(mapping.getExtAttrName());
-
-                                if (attribute != null && attribute.getValue() != null) {
-                                    for (Object obj : attribute.getValue()) {
-                                        if (obj != null) {
-                                            virAttr.getValues().add(obj.toString());
-                                        }
-                                    }
-                                }
-                            }
-
-                            toBeCached.setResourceValues(resource.getKey(), new HashSet<>(virAttr.getValues()));
+    private AttrTO evaluateAttrFromTemplate(final AnyTO anyTO, final AttrTO template) {
+        AttrTO result = new AttrTO();
+        result.setSchema(template.getSchema());
 
-                            LOG.debug("Retrieved values {}", virAttr.getValues());
-                        }
-                    } catch (Exception e) {
-                        LOG.error("Error reading connector object from {}", resource.getKey(), e);
-
-                        if (virAttrCacheValue != null) {
-                            toBeCached.forceExpiring();
-                            LOG.debug("Search for a cached value (even expired!) ...");
-                            final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
-                            if (cachedValues != null) {
-                                LOG.debug("Use cached value {}", cachedValues);
-                                virAttr.getValues().addAll(cachedValues);
-                                toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
-                            }
-                        }
-                    }
+        if (template.getValues() != null && !template.getValues().isEmpty()) {
+            for (String value : template.getValues()) {
+                String evaluated = JexlUtils.evaluate(value, anyTO);
+                if (StringUtils.isNotBlank(evaluated)) {
+                    result.getValues().add(evaluated);
                 }
             }
-
-            virAttrCache.put(any.getType().getKey(), any.getKey(), schemaName, toBeCached);
         }
-    }
-
-    private Collection<ExternalResource> getTargetResources(
-            final VirAttr<?> attr, final IntMappingType type, final AnyUtils anyUtils, final AnyType anyType) {
-
-        Iterable<? extends ExternalResource> iterable = attr.getOwner() instanceof User
-                ? userDAO.findAllResources((User) attr.getOwner())
-                : attr.getOwner() instanceof AnyObject
-                        ? anyObjectDAO.findAllResources((AnyObject) attr.getOwner())
-                        : attr.getOwner() instanceof Group
-                                ? ((Group) attr.getOwner()).getResources()
-                                : Collections.<ExternalResource>emptySet();
-        return getTargetResources(attr, type, anyUtils, iterable, anyType);
-    }
-
-    private Collection<ExternalResource> getTargetResources(final VirAttr<?> attr, final IntMappingType type,
-            final AnyUtils anyUtils, final Iterable<? extends ExternalResource> ownerResources, final AnyType anyType) {
-
-        return CollectionUtils.select(ownerResources, new Predicate<ExternalResource>() {
 
-            @Override
-            public boolean evaluate(final ExternalResource resource) {
-                return resource.getProvision(anyType) != null
-                        && !MappingUtils.getMatchingMappingItems(
-                                anyUtils.getMappingItems(resource.getProvision(anyType), MappingPurpose.BOTH),
-                                attr.getSchema().getKey(), type).isEmpty();
-            }
-        });
+        return result;
     }
 
     private void fillFromTemplate(final AnyTO anyTO, final AnyTO template) {
+        if (template.getRealm() != null) {
+            anyTO.setRealm(template.getRealm());
+        }
+
         Map<String, AttrTO> currentAttrMap = anyTO.getPlainAttrMap();
-        for (AttrTO templateAttr : template.getPlainAttrs()) {
-            if (templateAttr.getValues() != null && !templateAttr.getValues().isEmpty()
-                    && (!currentAttrMap.containsKey(templateAttr.getSchema())
-                    || currentAttrMap.get(templateAttr.getSchema()).getValues().isEmpty())) {
+        for (AttrTO templatePlainAttr : template.getPlainAttrs()) {
+            if (!templatePlainAttr.getValues().isEmpty()
+                    && (!currentAttrMap.containsKey(templatePlainAttr.getSchema())
+                    || currentAttrMap.get(templatePlainAttr.getSchema()).getValues().isEmpty())) {
 
-                anyTO.getPlainAttrs().add(evaluateAttrTemplate(anyTO, templateAttr));
+                anyTO.getPlainAttrs().add(evaluateAttrFromTemplate(anyTO, templatePlainAttr));
             }
         }
 
@@ -644,29 +481,39 @@ public class ConnObjectUtils {
 
         currentAttrMap = anyTO.getVirAttrMap();
         for (AttrTO templateVirAttr : template.getVirAttrs()) {
-            if (templateVirAttr.getValues() != null && !templateVirAttr.getValues().isEmpty()
+            if (!templateVirAttr.getValues().isEmpty()
                     && (!currentAttrMap.containsKey(templateVirAttr.getSchema())
                     || currentAttrMap.get(templateVirAttr.getSchema()).getValues().isEmpty())) {
 
-                anyTO.getVirAttrs().add(evaluateAttrTemplate(anyTO, templateVirAttr));
+                anyTO.getVirAttrs().add(evaluateAttrFromTemplate(anyTO, templateVirAttr));
             }
         }
+
+        for (String resource : template.getResources()) {
+            anyTO.getResources().add(resource);
+        }
+
+        anyTO.getAuxClasses().addAll(template.getAuxClasses());
     }
 
-    private AttrTO evaluateAttrTemplate(final AnyTO anyTO, final AttrTO template) {
-        AttrTO result = new AttrTO();
-        result.setSchema(template.getSchema());
+    private void fillRelationshipsFromTemplate(final Map<Long, RelationshipTO> anyRelMap,
+            final List<RelationshipTO> anyRels, final List<RelationshipTO> templateRels) {
 
-        if (template.getValues() != null && !template.getValues().isEmpty()) {
-            for (String value : template.getValues()) {
-                String evaluated = JexlUtils.evaluate(value, anyTO);
-                if (StringUtils.isNotBlank(evaluated)) {
-                    result.getValues().add(evaluated);
-                }
+        for (RelationshipTO memb : templateRels) {
+            if (!anyRelMap.containsKey(memb.getRightKey())) {
+                anyRels.add(memb);
             }
         }
+    }
 
-        return result;
+    private void fillMembershipsFromTemplate(final Map<Long, MembershipTO> anyMembMap,
+            final List<MembershipTO> anyMembs, final List<MembershipTO> templateMembs) {
+
+        for (MembershipTO memb : templateMembs) {
+            if (!anyMembMap.containsKey(memb.getRightKey())) {
+                anyMembs.add(memb);
+            }
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
index a1931c1..2efae81 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
@@ -64,6 +64,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.identityconnectors.framework.common.FrameworkUtil;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
@@ -230,7 +231,7 @@ public final class MappingUtils {
 
         ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext();
         AnyUtilsFactory anyUtilsFactory = context.getBean(AnyUtilsFactory.class);
-        ConnObjectUtils connObjectUtils = context.getBean(ConnObjectUtils.class);
+        VirAttrHandler virAttrHandler = context.getBean(VirAttrHandler.class);
 
         switch (mapItem.getIntMappingType().getAnyTypeKind()) {
             case USER:
@@ -243,7 +244,7 @@ public final class MappingUtils {
                 if (any instanceof User) {
                     UserDAO userDAO = context.getBean(UserDAO.class);
                     for (Group group : userDAO.findAllGroups((User) any)) {
-                        connObjectUtils.retrieveVirAttrValues(group);
+                        virAttrHandler.retrieveVirAttrValues(group);
                         anys.add(group);
                     }
                 } else if (any instanceof Group) {
@@ -266,7 +267,7 @@ public final class MappingUtils {
         PlainSchema schema = null;
         boolean readOnlyVirSchema = false;
         AttrSchemaType schemaType;
-        final Pair<String, Attribute> result;
+        Pair<String, Attribute> result;
 
         switch (mapItem.getIntMappingType()) {
             case UserPlainSchema:
@@ -290,7 +291,7 @@ public final class MappingUtils {
                 schemaType = AttrSchemaType.String;
         }
 
-        final String extAttrName = mapItem.getExtAttrName();
+        String extAttrName = mapItem.getExtAttrName();
 
         LOG.debug("Define mapping for: "
                 + "\n* ExtAttrName " + extAttrName
@@ -389,7 +390,7 @@ public final class MappingUtils {
         if (StringUtils.isNotBlank(anyUtils.getConnObjectLink(provision))) {
             final JexlContext jexlContext = new MapContext();
             JexlUtils.addFieldsToContext(any, jexlContext);
-            JexlUtils.addAttrsToContext(any.getPlainAttrs(), jexlContext);
+            JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
             JexlUtils.addDerAttrsToContext(any.getDerAttrs(), any.getPlainAttrs(), jexlContext);
             evalConnObjectLink = JexlUtils.evaluate(anyUtils.getConnObjectLink(provision), jexlContext);
         }
@@ -443,6 +444,8 @@ public final class MappingUtils {
 
         EntityFactory entityFactory =
                 ApplicationContextProvider.getApplicationContext().getBean(EntityFactory.class);
+        AnyUtilsFactory anyUtilsFactory =
+                ApplicationContextProvider.getApplicationContext().getBean(AnyUtilsFactory.class);
         List<PlainAttrValue> values = new ArrayList<>();
         PlainAttrValue attrValue;
         switch (mappingItem.getIntMappingType()) {
@@ -472,6 +475,7 @@ public final class MappingUtils {
             case GroupVirtualSchema:
             case AnyVirtualSchema:
                 for (Any<?, ?, ?> any : anys) {
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     VirAttr<?> virAttr = any.getVirAttr(mappingItem.getIntAttrName());
                     if (virAttr != null) {
                         if (vAttrsToBeRemoved != null && vAttrsToBeUpdated != null) {
@@ -488,7 +492,7 @@ public final class MappingUtils {
                         }
                         if (virAttr.getValues() != null) {
                             for (String value : virAttr.getValues()) {
-                                attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                                attrValue = anyUtils.newPlainAttrValue();
                                 attrValue.setStringValue(value);
                                 values.add(attrValue);
                             }
@@ -508,11 +512,10 @@ public final class MappingUtils {
             case GroupDerivedSchema:
             case AnyDerivedSchema:
                 for (Any<?, ?, ?> any : anys) {
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     DerAttr<?> derAttr = any.getDerAttr(mappingItem.getIntAttrName());
                     if (derAttr != null) {
-                        attrValue = any instanceof Group
-                                ? entityFactory.newEntity(GPlainAttrValue.class)
-                                : entityFactory.newEntity(UPlainAttrValue.class);
+                        attrValue = anyUtils.newPlainAttrValue();
                         attrValue.setStringValue(derAttr.getValue(any.getPlainAttrs()));
                         values.add(attrValue);
                     }
@@ -529,7 +532,8 @@ public final class MappingUtils {
             case GroupId:
             case AnyId:
                 for (Any<?, ?, ?> any : anys) {
-                    attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                    attrValue = anyUtils.newPlainAttrValue();
                     attrValue.setStringValue(any.getKey().toString());
                     values.add(attrValue);
                 }
@@ -600,7 +604,6 @@ public final class MappingUtils {
      * @return connObjectKey internal value
      */
     public static String getConnObjectKeyValue(final Any<?, ?, ?> any, final Provision provision) {
-
         List<PlainAttrValue> values = getIntValues(provision, provision.getMapping().getConnObjectKeyItem(),
                 Collections.<Any<?, ?, ?>>singletonList(any), null, null);
         return values == null || values.isEmpty()

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
index 83e98ec..9aad079 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
@@ -146,7 +146,7 @@ public final class JexlUtils {
         return context;
     }
 
-    public static JexlContext addAttrsToContext(final Collection<? extends PlainAttr<?>> attrs,
+    public static JexlContext addPlainAttrsToContext(final Collection<? extends PlainAttr<?>> attrs,
             final JexlContext jexlContext) {
 
         JexlContext context = jexlContext == null
@@ -215,11 +215,9 @@ public final class JexlUtils {
         return context;
     }
 
-    public static boolean evaluateMandatoryCondition(
-            final String mandatoryCondition, final Any<?, ?, ?> any) {
-
+    public static boolean evaluateMandatoryCondition(final String mandatoryCondition, final Any<?, ?, ?> any) {
         JexlContext jexlContext = new MapContext();
-        addAttrsToContext(any.getPlainAttrs(), jexlContext);
+        addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
         addDerAttrsToContext(any.getDerAttrs(), any.getPlainAttrs(), jexlContext);
         addVirAttrsToContext(any.getVirAttrs(), jexlContext);
 
@@ -229,8 +227,8 @@ public final class JexlUtils {
     public static String evaluate(final String expression,
             final Any<?, ?, ?> any, final Collection<? extends PlainAttr<?>> attributes) {
 
-        final JexlContext jexlContext = new MapContext();
-        JexlUtils.addAttrsToContext(attributes, jexlContext);
+        JexlContext jexlContext = new MapContext();
+        JexlUtils.addPlainAttrsToContext(attributes, jexlContext);
         JexlUtils.addFieldsToContext(any, jexlContext);
 
         // Evaluate expression using the context prepared before

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
new file mode 100644
index 0000000..04f67dd
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.api.dao;
+
+public class UnallowedSchemaException extends RuntimeException {
+
+    private static final long serialVersionUID = -9206535191442808016L;
+
+    public UnallowedSchemaException(final String schemaName) {
+        super(schemaName + " not allowed");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
index ddb047e..19d0f6b 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
@@ -27,7 +27,7 @@ public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
     boolean remove(ARelationship relationship);
 
-    ARelationship getRelationship(AnyObject rightEnd);
+    ARelationship getRelationship(Long relationshipKey);
 
     List<? extends ARelationship> getRelationships();
 
@@ -35,7 +35,7 @@ public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
     boolean remove(AMembership membership);
 
-    AMembership getMembership(Long groupKey);
+    AMembership getMembership(Long membershipKey);
 
     List<? extends AMembership> getMemberships();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
index e1b9a5e..296de84 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity.task;
 
-import java.util.List;
+import java.util.Set;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -29,7 +29,7 @@ public interface ProvisioningTask extends SchedTask {
 
     void setResource(ExternalResource resource);
 
-    List<String> getActionsClassNames();
+    Set<String> getActionsClassNames();
 
     MatchingRule getMatchingRule();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index d896984..f02c555 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -23,7 +23,6 @@ import java.util.List;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Role;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 
 public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
 
@@ -133,7 +132,7 @@ public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
 
     boolean remove(URelationship relationship);
 
-    URelationship getRelationship(AnyObject rightEnd);
+    URelationship getRelationship(Long anyObjectKey);
 
     List<? extends URelationship> getRelationships();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 3448737..ef2161e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -89,7 +89,8 @@ public abstract class AbstractAnyDAO<A extends Any<?, ?, ?>> extends AbstractDAO
 
         A any = find(key);
         if (any == null) {
-            throw new NotFoundException("Any " + key);
+            throw new NotFoundException(StringUtils.substringBefore(
+                    StringUtils.substringAfter(getClass().getSimpleName(), "JPA"), "DAO") + " " + key);
         }
 
         securityChecks(any);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
index a849ef5..18b6636 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPADerSchemaDAO extends AbstractDAO<DerSchema, String> implements D
             resourceDAO.deleteMapping(key, anyUtils.derIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index 50865c3..c3c94ce 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implemen
             resourceDAO.deleteMapping(key, anyUtils.plainIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index cc4ffe4..dae6afc 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V
             resourceDAO.deleteMapping(key, anyUtils.virIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
index 914bd02..ec37649 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.util.Collections;
 import java.util.Set;
+import org.apache.syncope.core.persistence.api.dao.UnallowedSchemaException;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Attr;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
@@ -53,7 +54,7 @@ public abstract class AbstractAttr<S extends Schema, O extends Any<?, ?, ?>>
         }
 
         if (!getAllowedSchemas(getOwner()).contains(schema)) {
-            throw new IllegalArgumentException(schema + " not allowed for this instance");
+            throw new UnallowedSchemaException(schema.getKey());
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
index fba234d..4500a4e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
@@ -21,9 +21,6 @@ package org.apache.syncope.core.persistence.jpa.entity;
 import java.util.Collection;
 import javax.persistence.Column;
 import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
@@ -38,20 +35,11 @@ public abstract class AbstractDerAttr<O extends Any<?, ?, ?>>
 
     private static final long serialVersionUID = 4740924251090424771L;
 
-    @Id
-    @GeneratedValue(strategy = GenerationType.AUTO)
-    protected Long id;
-
     @ManyToOne(fetch = FetchType.EAGER)
     @Column(name = "schema_name")
     private JPADerSchema schema;
 
     @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
     public DerSchema getSchema() {
         return schema;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
index 946b09b..aebc8da 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
@@ -22,9 +22,6 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.Column;
 import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 import javax.persistence.Transient;
@@ -38,10 +35,6 @@ public abstract class AbstractVirAttr<O extends Any<?, ?, ?>>
 
     private static final long serialVersionUID = 5023204776925954907L;
 
-    @Id
-    @GeneratedValue(strategy = GenerationType.AUTO)
-    protected Long id;
-
     @Transient
     protected List<String> values = new ArrayList<>();
 
@@ -50,11 +43,6 @@ public abstract class AbstractVirAttr<O extends Any<?, ?, ?>>
     private JPAVirSchema schema;
 
     @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
     public List<String> getValues() {
         return values;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
index abd6676..1525de9 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
@@ -33,10 +34,18 @@ public class JPAADerAttr extends AbstractDerAttr<AnyObject> implements ADerAttr
 
     public static final String TABLE = "ADerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAAnyObject owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public AnyObject getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
index 7469799..62e2ea5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
@@ -33,10 +34,18 @@ public class JPAAVirAttr extends AbstractVirAttr<AnyObject> implements AVirAttr
 
     public static final String TABLE = "AVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAAnyObject owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public AnyObject getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index 6442c2d..a8e842b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -198,12 +198,12 @@ public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> im
     }
 
     @Override
-    public ARelationship getRelationship(final AnyObject rightEnd) {
+    public ARelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<ARelationship>() {
 
             @Override
             public boolean evaluate(final ARelationship relationship) {
-                return rightEnd != null && rightEnd.equals(relationship.getRightEnd());
+                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
index 46fc1cd..73911f8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.group.GDerAttr;
@@ -33,10 +34,18 @@ public class JPAGDerAttr extends AbstractDerAttr<Group> implements GDerAttr {
 
     public static final String TABLE = "GDerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAGroup owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public Group getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
index 302e056..47b8886 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
@@ -33,10 +34,18 @@ public class JPAGVirAttr extends AbstractVirAttr<Group> implements GVirAttr {
 
     public static final String TABLE = "GVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAGroup owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public Group getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
index d90f605..7af8491 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
@@ -87,7 +87,9 @@ public class JPAAnyTemplate extends AbstractEntity<Long> implements AnyTemplate
                 ? anyType == null
                         ? null
                         : new JPAAnyUtilsFactory().getInstance(anyType.getKind()).newAnyTO()
-                : POJOHelper.deserialize(template, AnyTO.class);
+                : anyType == null
+                        ? null
+                        : POJOHelper.deserialize(template, anyType.getKind().getToClass());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
index 07e6f00..0592a9d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.persistence.jpa.entity.task;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
@@ -48,7 +50,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
     @CollectionTable(name = "PushTask_actionsClassNames",
             joinColumns =
             @JoinColumn(name = "pushTask_id", referencedColumnName = "id"))
-    private List<String> actionsClassNames = new ArrayList<>();
+    private Set<String> actionsClassNames = new HashSet<>();
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pushTask")
     private List<JPAAnyFilter> filters = new ArrayList<>();
@@ -61,7 +63,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
     }
 
     @Override
-    public List<String> getActionsClassNames() {
+    public Set<String> getActionsClassNames() {
         return actionsClassNames;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
index 0106a65..41eb4ea 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.persistence.jpa.entity.task;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
@@ -57,7 +59,7 @@ public class JPASyncTask extends AbstractProvisioningTask implements SyncTask {
     @CollectionTable(name = "SyncTask_actionsClassNames",
             joinColumns =
             @JoinColumn(name = "syncTask_id", referencedColumnName = "id"))
-    private List<String> actionsClassNames = new ArrayList<>();
+    private Set<String> actionsClassNames = new HashSet<>();
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "syncTask")
     private List<JPAAnyTemplate> templates = new ArrayList<>();
@@ -86,7 +88,7 @@ public class JPASyncTask extends AbstractProvisioningTask implements SyncTask {
     }
 
     @Override
-    public List<String> getActionsClassNames() {
+    public Set<String> getActionsClassNames() {
         return actionsClassNames;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
index 90bee1b..754fd59 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.user.UDerAttr;
@@ -33,10 +34,18 @@ public class JPAUDerAttr extends AbstractDerAttr<User> implements UDerAttr {
 
     public static final String TABLE = "UDerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAUser owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public User getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
index 56898d4..50ce967 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
@@ -45,9 +45,6 @@ public class JPAUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr
 
     public static final String TABLE = "UPlainAttr";
 
-    /**
-     * Auto-generated id for this table.
-     */
     @Id
     private Long id;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
index 52a168e..a6931ce 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
@@ -33,10 +34,18 @@ public class JPAUVirAttr extends AbstractVirAttr<User> implements UVirAttr {
 
     public static final String TABLE = "UVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAUser owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public User getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index f9c0c81..06d8f04 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -65,7 +65,6 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.Role;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
@@ -538,12 +537,12 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme
     }
 
     @Override
-    public URelationship getRelationship(final AnyObject rightEnd) {
+    public URelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<URelationship>() {
 
             @Override
             public boolean evaluate(final URelationship relationship) {
-                return rightEnd != null && rightEnd.equals(relationship.getRightEnd());
+                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
index c592c31..a75e4b6 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
@@ -312,6 +312,56 @@ under the License.
     </attributes>
   </entity>
 
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
   <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
     <attributes>
       <id name="id">