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 2016/06/22 06:43:59 UTC

[4/5] syncope git commit: [SYNCOPE-874] Most of work done on core; console implementation is missing

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
index 71328f4..5159088 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
@@ -25,19 +25,20 @@ import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 
 public interface PropagationManager {
 
     /**
-     * Create the any object tasks for every associated resource, unless in {@code noPropResourceNames}.
+     * Create the any object tasks for every associated resource, unless in {@code noPropResourceKeys}.
      *
      * @param kind any object type kind
      * @param key any object key
      * @param propByRes operation to be performed per resource
      * @param vAttrs virtual attributes to be set
-     * @param noPropResourceNames external resources performing not to be considered for propagation
+     * @param noPropResourceKeys external resources performing not to be considered for propagation
      * @return list of propagation tasks
      */
     List<PropagationTask> getCreateTasks(
@@ -45,17 +46,17 @@ public interface PropagationManager {
             String key,
             PropagationByResource propByRes,
             Collection<AttrTO> vAttrs,
-            Collection<String> noPropResourceNames);
+            Collection<String> noPropResourceKeys);
 
     /**
-     * Create the user tasks for every associated resource, unless in {@code noPropResourceNames}.
+     * Create the user tasks for every associated resource, unless in {@code noPropResourceKeys}.
      *
      * @param key user key
      * @param password to be set
      * @param enable whether user must be enabled or not
      * @param propByRes operation to be performed per resource
      * @param vAttrs virtual attributes to be set
-     * @param noPropResourceNames external resources not to be considered for propagation
+     * @param noPropResourceKeys external resources not to be considered for propagation
      * @return list of propagation tasks
      */
     List<PropagationTask> getUserCreateTasks(
@@ -64,10 +65,10 @@ public interface PropagationManager {
             Boolean enable,
             PropagationByResource propByRes,
             Collection<AttrTO> vAttrs,
-            Collection<String> noPropResourceNames);
+            Collection<String> noPropResourceKeys);
 
     /**
-     * Create the update tasks for the any object on each resource associated, unless in {@code noPropResourceNames}.
+     * Create the update tasks for the any object on each resource associated, unless in {@code noPropResourceKeys}.
      *
      * @param kind any object type kind
      * @param key any object key
@@ -75,7 +76,7 @@ public interface PropagationManager {
      * @param enable whether any object should be enabled or not, may be null to leave unchanged
      * @param propByRes operation to be performed per resource
      * @param vAttrs virtual attributes to be set
-     * @param noPropResourceNames external resource names not to be considered for propagation
+     * @param noPropResourceKeys external resource keys not to be considered for propagation
      * @return list of propagation tasks
      */
     List<PropagationTask> getUpdateTasks(
@@ -85,20 +86,20 @@ public interface PropagationManager {
             Boolean enable,
             PropagationByResource propByRes,
             Collection<AttrTO> vAttrs,
-            Collection<String> noPropResourceNames);
+            Collection<String> noPropResourceKeys);
 
     /**
-     * Create the update tasks for the user on each resource associated, unless in {@code noPropResourceNames}.
+     * Create the update tasks for the user on each resource associated, unless in {@code noPropResourceKeys}.
      *
      * @param wfResult user to be propagated (and info associated), as per result from workflow
      * @param changePwd whether password should be included for propagation attributes or not
-     * @param noPropResourceNames external resources not to be considered for propagation
+     * @param noPropResourceKeys external resources not to be considered for propagation
      * @return list of propagation tasks
      */
     List<PropagationTask> getUserUpdateTasks(
             WorkflowResult<Pair<UserPatch, Boolean>> wfResult,
             boolean changePwd,
-            Collection<String> noPropResourceNames);
+            Collection<String> noPropResourceKeys);
 
     /**
      * Create the update tasks for the user on each resource associated; propagate password update only to requested
@@ -110,18 +111,30 @@ public interface PropagationManager {
     List<PropagationTask> getUserUpdateTasks(WorkflowResult<Pair<UserPatch, Boolean>> wfResult);
 
     /**
-     * Create the delete tasks for the any object from each resource associated, unless in {@code noPropResourceNames}.
+     * Create the delete tasks for the any object from each resource associated, unless in {@code noPropResourceKeys}.
      *
      * @param kind any object type kind
      * @param key any object key
      * @param propByRes operation to be performed per resource
-     * @param noPropResourceNames external resource names not to be considered for propagation
+     * @param noPropResourceKeys external resource keys not to be considered for propagation
      * @return list of propagation tasks
      */
     List<PropagationTask> getDeleteTasks(
             AnyTypeKind kind,
             String key,
             PropagationByResource propByRes,
-            Collection<String> noPropResourceNames);
+            Collection<String> noPropResourceKeys);
 
+    /**
+     * Create the needed tasks for the realm for each resource associated, unless in {@code noPropResourceKeys}.
+     *
+     * @param realm realm
+     * @param propByRes operation to be performed per resource
+     * @param noPropResourceKeys external resource keys not to be considered for propagation
+     * @return list of propagation tasks
+     */
+    List<PropagationTask> createTasks(
+            Realm realm,
+            PropagationByResource propByRes,
+            Collection<String> noPropResourceKeys);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
index bb145c5..9666804 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.provisioning.api.pushpull;
 
 import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.identityconnectors.framework.common.objects.SyncDelta;
 import org.quartz.JobExecutionException;
 
@@ -31,110 +32,104 @@ import org.quartz.JobExecutionException;
 public interface PullActions extends ProvisioningActions {
 
     /**
-     * Action to be executed before to create a pulled user / group locally.
-     * User/group is created locally upon pull in case of the un-matching rule
+     * Action to be executed before to create a pulled entity locally.
+     * The entity is created locally upon pull in case of the un-matching rule
      * {@link org.apache.syncope.common.lib.types.UnmatchingRule#PROVISION} (default un-matching rule) is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeProvision(
+    SyncDelta beforeProvision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before creating (and linking to the resource) a pulled user / group locally.
-     * User/group is created locally and linked to the pulled resource upon pull in case of the
+     * Action to be executed before creating (and linking to the resource) a pulled entity locally.
+     * The entity is created locally and linked to the pulled resource upon pull in case of the
      * un-matching rule {@link org.apache.syncope.common.lib.types.UnmatchingRule#ASSIGN} is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeAssign(
+    SyncDelta beforeAssign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before unlinking resource from the pulled user / group and de-provisioning.
-     * User/group is unlinked and de-provisioned from the pulled resource upon pull in case of the
+     * Action to be executed before unlinking resource from the pulled entity and de-provisioning.
+     * The entity is unlinked and de-provisioned from the pulled resource upon pull in case of the
      * matching rule {@link org.apache.syncope.common.lib.types.MatchingRule#UNASSIGN} is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeUnassign(
+    SyncDelta beforeUnassign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
      * Action to be executed before de-provisioning action only.
-     * User/group is de-provisioned (without unlinking) from the pulled resource upon pull in case of
+     * The entity is de-provisioned (without unlinking) from the pulled resource upon pull in case of
      * the matching rule {@link org.apache.syncope.common.lib.types.MatchingRule#DEPROVISION} is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeDeprovision(
+    SyncDelta beforeDeprovision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before unlinking resource from the pulled user / group.
-     * User/group is unlinked (without de-provisioning) from the pulled resource upon pull in case of
+     * Action to be executed before unlinking resource from the pulled entity.
+     * The entity is unlinked (without de-provisioning) from the pulled resource upon pull in case of
      * the matching rule {@link org.apache.syncope.common.lib.types.MatchingRule#UNLINK} is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeUnlink(
+    SyncDelta beforeUnlink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before linking resource to the pulled user / group.
-     * User/group is linked (without updating) to the pulled resource upon pull in case of
+     * Action to be executed before linking resource to the pulled entity.
+     * The entity is linked (without updating) to the pulled resource upon pull in case of
      * the matching rule {@link org.apache.syncope.common.lib.types.MatchingRule#LINK} is applied.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
-     * @return pull information used for user status evaluation and to be passed to the 'after' method.
+     * @param entity entity
+     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeLink(
+    SyncDelta beforeLink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to update a pulled user / group locally.
-     * User/group is updated upon pull in case of the matching rule
+     * Action to be executed before to update a pulled entity locally.
+     * The entity is updated upon pull in case of the matching rule
      * {@link org.apache.syncope.common.lib.types.MatchingRule#UPDATE} (default matching rule) is applied.
      *
      * @param <M> concrete any object
@@ -154,35 +149,33 @@ public interface PullActions extends ProvisioningActions {
             throws JobExecutionException;
 
     /**
-     * Action to be executed before to delete a pulled user / group locally.
+     * Action to be executed before to delete a pulled entity locally.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object to be deleted
+     * @param entity entity
      * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> SyncDelta beforeDelete(
+    SyncDelta beforeDelete(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any) throws JobExecutionException;
+            EntityTO entity) throws JobExecutionException;
 
     /**
-     * Action to be executed after each local user / group pull.
+     * Action to be executed after each local entity pull.
      *
-     * @param <A> concrete any object
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information (may be modified by beforeProvision / beforeUpdate /
      * beforeDelete)
-     * @param any any object
+     * @param entity entity
      * @param result global pull results at the current pull step
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends AnyTO> void after(
+    void after(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            A any,
+            EntityTO entity,
             ProvisioningReport result) throws JobExecutionException;
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PushActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PushActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PushActions.java
index 93180d4..592c18b 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PushActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PushActions.java
@@ -18,146 +18,136 @@
  */
 package org.apache.syncope.core.provisioning.api.pushpull;
 
-import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.quartz.JobExecutionException;
 
 /**
  * Interface for actions to be performed during push.
- * All methods can throw {@link IgnoreProvisionException} to make the current any ignored by the push process.
+ * All methods can throw {@link IgnoreProvisionException} to make the current entity ignored by the push process.
  */
 public interface PushActions extends ProvisioningActions {
 
     /**
-     * Action to be executed before to assign (link &amp; provision) a synchronized any object to the resource.
+     * Action to be executed before to assign (link &amp; provision) a pushed entity to the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeAssign(
+    Entity beforeAssign(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to provision a synchronized any object to the resource.
+     * Action to be executed before to provision a pushed entity to the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeProvision(
+    Entity beforeProvision(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to update a synchronized any object on the resource.
+     * Action to be executed before to update a pushed entity on the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be updated.
-     * @return any.
+     * @param entity entity to be updated.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeUpdate(
+    Entity beforeUpdate(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to link a synchronized any object to the resource.
+     * Action to be executed before to link a pushed entity to the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeLink(
+    Entity beforeLink(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to unlink a synchronized any object from the resource.
+     * Action to be executed before to unlink a pushed entity from the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeUnlink(
+    Entity beforeUnlink(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to unassign a synchronized any object from the resource.
+     * Action to be executed before to unassign a pushed entity from the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeUnassign(
+    Entity beforeUnassign(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before to unassign a synchronized any object from the resource.
+     * Action to be executed before to unassign a pushed entity from the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeDeprovision(
+    Entity beforeDeprovision(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed before delete a synchronized any object locally and from the resource.
+     * Action to be executed before delete a pushed entity locally and from the resource.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any any object to be created.
-     * @return any.
+     * @param entity entity to be created.
+     * @return entity.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> A beforeDelete(
+    Entity beforeDelete(
             ProvisioningProfile<?, ?> profile,
-            A any) throws JobExecutionException;
+            Entity entity) throws JobExecutionException;
 
     /**
-     * Action to be executed after any object push goes on error.
+     * Action to be executed after entity push goes on error.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any synchronized any object.
+     * @param entity pushed entity.
      * @param result operation result.
      * @param error error being reported
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> void onError(
+    void onError(
             ProvisioningProfile<?, ?> profile,
-            A any,
+            Entity entity,
             ProvisioningReport result,
             Exception error) throws JobExecutionException;
 
     /**
-     * Action to be executed after each local any object push.
+     * Action to be executed after each local entity push.
      *
-     * @param <A> concrete any object
      * @param profile profile of the push being executed.
-     * @param any synchronized any object.
+     * @param entity pushed entity.
      * @param result operation result.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?>> void after(
+    void after(
             ProvisioningProfile<?, ?> profile,
-            A any,
+            Entity entity,
             ProvisioningReport result) throws JobExecutionException;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
index ba124dd..8d32726 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
@@ -229,7 +229,7 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
                 AnyTypeKind.GROUP,
                 key,
                 propByRes,
-                CollectionUtils.removeAll(groupDAO.authFind(key).getResourceNames(), resources));
+                CollectionUtils.removeAll(groupDAO.authFind(key).getResourceKeys(), resources));
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         taskExecutor.execute(tasks, propagationReporter, nullPriorityAsync);

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index b826b63..f1e4270 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -496,10 +496,10 @@ abstract class AbstractAnyDataBinder {
         }
 
         // 2. resources
-        for (String resourceName : anyTO.getResources()) {
-            ExternalResource resource = resourceDAO.find(resourceName);
+        for (String resourceKey : anyTO.getResources()) {
+            ExternalResource resource = resourceDAO.find(resourceKey);
             if (resource == null) {
-                LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceName);
+                LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceKey);
             } else {
                 any.add(resource);
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index d129dcb..3ad0ac9 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -266,7 +266,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
         // name
         if (anyObjectPatch.getName() != null && StringUtils.isNotBlank(anyObjectPatch.getName().getValue())) {
-            propByRes.addAll(ResourceOperation.UPDATE, anyObject.getResourceNames());
+            propByRes.addAll(ResourceOperation.UPDATE, anyObject.getResourceKeys());
 
             anyObject.setName(anyObjectPatch.getName().getValue());
         }
@@ -294,7 +294,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
                         anyObject.getRelationships().remove(relationship);
                         relationship.setLeftEnd(null);
 
-                        toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+                        toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceKeys());
                     }
 
                     if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
@@ -319,7 +319,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
                                 anyObject.add(relationship);
 
-                                toBeProvisioned.addAll(otherEnd.getResourceNames());
+                                toBeProvisioned.addAll(otherEnd.getResourceKeys());
                             } else {
                                 LOG.error("{} cannot be assigned to {}", otherEnd, anyObject);
 
@@ -352,7 +352,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
                         attr.setOwner(null);
                     }
 
-                    toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
+                    toBeDeprovisioned.addAll(membership.getRightEnd().getResourceKeys());
                 }
 
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
@@ -397,7 +397,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
                             scce.addException(invalidValues);
                         }
 
-                        toBeProvisioned.addAll(group.getResourceNames());
+                        toBeProvisioned.addAll(group.getResourceKeys());
                     } else {
                         LOG.error("{} cannot be assigned to {}", group, anyObject);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index 38f1811..2306cdc 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -194,7 +194,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
 
         // name
         if (groupPatch.getName() != null && StringUtils.isNotBlank(groupPatch.getName().getValue())) {
-            propByRes.addAll(ResourceOperation.UPDATE, group.getResourceNames());
+            propByRes.addAll(ResourceOperation.UPDATE, group.getResourceKeys());
 
             group.setName(groupPatch.getName().getValue());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
index 38d94fd..f8f6334 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
@@ -25,8 +25,11 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTemplate;
@@ -37,6 +40,7 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.provisioning.api.data.RealmDataBinder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,6 +62,9 @@ public class RealmDataBinderImpl implements RealmDataBinder {
     private PolicyDAO policyDAO;
 
     @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     @Autowired
@@ -126,11 +133,20 @@ public class RealmDataBinderImpl implements RealmDataBinder {
 
         setTemplates(realmTO, realm);
 
+        for (String resourceKey : realmTO.getResources()) {
+            ExternalResource resource = resourceDAO.find(resourceKey);
+            if (resource == null) {
+                LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceKey);
+            } else {
+                realm.add(resource);
+            }
+        }
+
         return realm;
     }
 
     @Override
-    public void update(final Realm realm, final RealmTO realmTO) {
+    public PropagationByResource update(final Realm realm, final RealmTO realmTO) {
         realm.setName(realmTO.getName());
         realm.setParent(realmTO.getParent() == null ? null : realmDAO.find(realmTO.getParent()));
 
@@ -166,6 +182,31 @@ public class RealmDataBinderImpl implements RealmDataBinder {
         realm.getActionsClassNames().addAll(realmTO.getActionsClassNames());
 
         setTemplates(realmTO, realm);
+
+        final PropagationByResource propByRes = new PropagationByResource();
+        for (String resourceKey : realmTO.getResources()) {
+            ExternalResource resource = resourceDAO.find(resourceKey);
+            if (resource == null) {
+                LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceKey);
+            } else {
+                realm.add(resource);
+                propByRes.add(ResourceOperation.CREATE, resource.getKey());
+            }
+        }
+        // remove all resources not contained in the TO
+        CollectionUtils.filter(realm.getResources(), new Predicate<ExternalResource>() {
+
+            @Override
+            public boolean evaluate(final ExternalResource resource) {
+                boolean contained = realmTO.getResources().contains(resource.getKey());
+                if (!contained) {
+                    propByRes.add(ResourceOperation.DELETE, resource.getKey());
+                }
+                return contained;
+            }
+        });
+
+        return propByRes;
     }
 
     @Override
@@ -184,6 +225,10 @@ public class RealmDataBinderImpl implements RealmDataBinder {
             realmTO.getTemplates().put(template.getAnyType().getKey(), template.get());
         }
 
+        for (ExternalResource resource : realm.getResources()) {
+            realmTO.getResources().add(resource.getKey());
+        }
+
         return realmTO;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 7eea744..74d6f1a 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.MappingItemTO;
 import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.OrgUnitTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -53,6 +54,7 @@ import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
@@ -225,6 +227,42 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             }
         }
 
+        // 3. orgUnit
+        if (resourceTO.getOrgUnit() == null && resource.getOrgUnit() != null) {
+            resource.getOrgUnit().setResource(null);
+            resource.setOrgUnit(null);
+        } else if (resourceTO.getOrgUnit() != null) {
+            OrgUnitTO orgUnitTO = resourceTO.getOrgUnit();
+
+            OrgUnit orgUnit = resource.getOrgUnit();
+            if (orgUnit == null) {
+                orgUnit = entityFactory.newEntity(OrgUnit.class);
+                orgUnit.setResource(resource);
+                resource.setOrgUnit(orgUnit);
+            }
+
+            if (orgUnitTO.getObjectClass() == null) {
+                SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidOrgUnit);
+                sce.getElements().add("Null " + ObjectClass.class.getSimpleName());
+                throw sce;
+            }
+            orgUnit.setObjectClass(new ObjectClass(orgUnitTO.getObjectClass()));
+
+            if (orgUnitTO.getExtAttrName() == null) {
+                SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidOrgUnit);
+                sce.getElements().add("Null extAttrName");
+                throw sce;
+            }
+            orgUnit.setExtAttrName(orgUnitTO.getExtAttrName());
+
+            if (orgUnitTO.getConnObjectLink() == null) {
+                SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidOrgUnit);
+                sce.getElements().add("Null connObjectLink");
+                throw sce;
+            }
+            orgUnit.setConnObjectLink(orgUnitTO.getConnObjectLink());
+        }
+
         resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
         resource.setUpdateTraceLevel(resourceTO.getUpdateTraceLevel());
         resource.setDeleteTraceLevel(resourceTO.getDeleteTraceLevel());
@@ -313,10 +351,10 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                     item.setMapping(mapping);
                     if (item.isConnObjectKey()) {
                         if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
-                            throw new IllegalArgumentException("Virtual attributes cannot be set as ConnObjectKey");
+                            invalidMapping.getElements().add("Virtual attributes cannot be set as ConnObjectKey");
                         }
                         if ("password".equals(intAttrName.getField())) {
-                            throw new IllegalArgumentException("Password attributes cannot be set as ConnObjectKey");
+                            invalidMapping.getElements().add("Password attributes cannot be set as ConnObjectKey");
                         }
 
                         mapping.setConnObjectKeyItem(item);
@@ -429,6 +467,19 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             resourceTO.getProvisions().add(provisionTO);
         }
 
+        if (resource.getOrgUnit() != null) {
+            OrgUnit orgUnit = resource.getOrgUnit();
+
+            OrgUnitTO orgUnitTO = new OrgUnitTO();
+            orgUnitTO.setKey(orgUnit.getKey());
+            orgUnitTO.setObjectClass(orgUnit.getObjectClass().getObjectClassValue());
+            orgUnitTO.setSyncToken(orgUnit.getSerializedSyncToken());
+            orgUnitTO.setExtAttrName(orgUnit.getExtAttrName());
+            orgUnitTO.setConnObjectLink(orgUnit.getConnObjectLink());
+            
+            resourceTO.setOrgUnit(orgUnitTO);
+        }
+
         resourceTO.setEnforceMandatoryCondition(resource.isEnforceMandatoryCondition());
 
         resourceTO.setPropagationPriority(resource.getPropagationPriority());

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 5a532d7..422e769 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -400,7 +400,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                         user.getRelationships().remove(relationship);
                         relationship.setLeftEnd(null);
 
-                        toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+                        toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceKeys());
                     }
 
                     if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
@@ -415,7 +415,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
 
                             user.add(relationship);
 
-                            toBeProvisioned.addAll(otherEnd.getResourceNames());
+                            toBeProvisioned.addAll(otherEnd.getResourceKeys());
                         } else {
                             LOG.error("{} cannot be assigned to {}", otherEnd, user);
 
@@ -448,7 +448,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                         attr.setMembership(null);
                     }
 
-                    toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
+                    toBeDeprovisioned.addAll(membership.getRightEnd().getResourceKeys());
                 }
 
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
@@ -493,7 +493,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                             scce.addException(invalidValues);
                         }
 
-                        toBeProvisioned.addAll(group.getResourceNames());
+                        toBeProvisioned.addAll(group.getResourceKeys());
 
                         // SYNCOPE-686: if password is invertible and we are adding resources with password mapping,
                         // ensure that they are counted for password propagation

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/GroupMemberProvisionTaskJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/GroupMemberProvisionTaskJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/GroupMemberProvisionTaskJobDelegate.java
index 3040d13..3c115b7 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/GroupMemberProvisionTaskJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/GroupMemberProvisionTaskJobDelegate.java
@@ -86,8 +86,8 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
         List<User> users = searchDAO.search(SearchCond.getLeafCond(membershipCond), AnyTypeKind.USER);
         for (User user : users) {
             List<PropagationStatus> statuses = actionType == BulkMembersActionType.DEPROVISION
-                    ? userProvisioningManager.deprovision(user.getKey(), group.getResourceNames(), false)
-                    : userProvisioningManager.provision(user.getKey(), true, null, group.getResourceNames(), false);
+                    ? userProvisioningManager.deprovision(user.getKey(), group.getResourceKeys(), false)
+                    : userProvisioningManager.provision(user.getKey(), true, null, group.getResourceKeys(), false);
             for (PropagationStatus status : statuses) {
                 result.append("User ").append(user.getKey()).append('\t').
                         append("Resource ").append(status.getResource()).append('\t').
@@ -105,8 +105,8 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
         List<AnyObject> anyObjects = searchDAO.search(SearchCond.getLeafCond(membershipCond), AnyTypeKind.ANY_OBJECT);
         for (AnyObject anyObject : anyObjects) {
             List<PropagationStatus> statuses = actionType == BulkMembersActionType.DEPROVISION
-                    ? anyObjectProvisioningManager.deprovision(anyObject.getKey(), group.getResourceNames(), false)
-                    : anyObjectProvisioningManager.provision(anyObject.getKey(), group.getResourceNames(), false);
+                    ? anyObjectProvisioningManager.deprovision(anyObject.getKey(), group.getResourceKeys(), false)
+                    : anyObjectProvisioningManager.provision(anyObject.getKey(), group.getResourceKeys(), false);
 
             for (PropagationStatus status : statuses) {
                 result.append(anyObject.getType().getKey()).append(' ').append(anyObject.getKey()).append('\t').

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index 3509bfe..2aabfd9 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -271,25 +271,25 @@ public class NotificationManagerImpl implements NotificationManager {
         } else if (output instanceof UserTO) {
             any = userDAO.find(((UserTO) output).getKey());
         } else if (output instanceof ProvisioningResult
-                && ((ProvisioningResult) output).getAny() instanceof UserTO) {
+                && ((ProvisioningResult) output).getEntity() instanceof UserTO) {
 
-            any = userDAO.find(((ProvisioningResult) output).getAny().getKey());
+            any = userDAO.find(((ProvisioningResult) output).getEntity().getKey());
         } else if (before instanceof AnyObjectTO) {
             any = anyObjectDAO.find(((AnyObjectTO) before).getKey());
         } else if (output instanceof AnyObjectTO) {
             any = anyObjectDAO.find(((AnyObjectTO) output).getKey());
         } else if (output instanceof ProvisioningResult
-                && ((ProvisioningResult) output).getAny() instanceof AnyObjectTO) {
+                && ((ProvisioningResult) output).getEntity() instanceof AnyObjectTO) {
 
-            any = anyObjectDAO.find(((ProvisioningResult) output).getAny().getKey());
+            any = anyObjectDAO.find(((ProvisioningResult) output).getEntity().getKey());
         } else if (before instanceof GroupTO) {
             any = groupDAO.find(((GroupTO) before).getKey());
         } else if (output instanceof GroupTO) {
             any = groupDAO.find(((GroupTO) output).getKey());
         } else if (output instanceof ProvisioningResult
-                && ((ProvisioningResult) output).getAny() instanceof GroupTO) {
+                && ((ProvisioningResult) output).getEntity() instanceof GroupTO) {
 
-            any = groupDAO.find(((ProvisioningResult) output).getAny().getKey());
+            any = groupDAO.find(((ProvisioningResult) output).getEntity().getKey());
         }
 
         AnyType anyType = any == null ? null : any.getType();

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index a1b5434..a8f70e1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -48,13 +48,16 @@ import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
 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.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 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.resource.OrgUnit;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.AuditManager;
@@ -65,12 +68,16 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationException
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.exceptions.ConnectorException;
 import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
 import org.identityconnectors.framework.common.objects.Name;
 import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.OperationOptionsBuilder;
+import org.identityconnectors.framework.common.objects.ResultsHandler;
 import org.identityconnectors.framework.common.objects.Uid;
+import org.identityconnectors.framework.common.objects.filter.EqualsFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -113,6 +120,12 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     protected GroupDAO groupDAO;
 
     /**
+     * Realm DAO.
+     */
+    @Autowired
+    protected RealmDAO realmDAO;
+
+    /**
      * Task DAO.
      */
     @Autowired
@@ -275,30 +288,30 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     protected Any<?> getAny(final PropagationTask task) {
         Any<?> any = null;
 
-        if (task.getAnyKey() != null) {
+        if (task.getEntityKey() != null && task.getAnyTypeKind() != null) {
             switch (task.getAnyTypeKind()) {
                 case USER:
                     try {
-                        any = userDAO.authFind(task.getAnyKey());
+                        any = userDAO.authFind(task.getEntityKey());
                     } catch (Exception e) {
-                        LOG.error("Could not read user {}", task.getAnyKey(), e);
+                        LOG.error("Could not read user {}", task.getEntityKey(), e);
                     }
                     break;
 
                 case GROUP:
                     try {
-                        any = groupDAO.authFind(task.getAnyKey());
+                        any = groupDAO.authFind(task.getEntityKey());
                     } catch (Exception e) {
-                        LOG.error("Could not read group {}", task.getAnyKey(), e);
+                        LOG.error("Could not read group {}", task.getEntityKey(), e);
                     }
                     break;
 
                 case ANY_OBJECT:
                 default:
                     try {
-                        any = anyObjectDAO.authFind(task.getAnyKey());
+                        any = anyObjectDAO.authFind(task.getEntityKey());
                     } catch (Exception e) {
-                        LOG.error("Could not read any object {}", task.getAnyKey(), e);
+                        LOG.error("Could not read any object {}", task.getEntityKey(), e);
                     }
                     break;
             }
@@ -320,17 +333,17 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         } else {
             /*
              * We must choose here whether to
-             * a. actually delete the provided any object from the external resource
-             * b. just update the provided any object data onto the external resource
+             * a. actually delete the provided entity from the external resource
+             * b. just update the provided entity data onto the external resource
              *
-             * (a) happens when either there is no any object associated with the PropagationTask (this takes place
-             * when the task is generated via UserLogic.delete() / GroupLogic.delete()) or the provided updated
-             * any object hasn't the current resource assigned (when the task is generated via
-             * UserController.update() / GroupLogic.update()).
+             * (a) happens when either there is no entity associated with the PropagationTask (this takes place
+             * when the task is generated via Logic's delete()) or the provided updated
+             * entity hasn't the current resource assigned (when the task is generated via
+             * Logic's update()).
              *
-             * (b) happens when the provided updated any object does have the current resource assigned (when the task
-             * is generated via UserLogic.update() / GroupLogic.updae()): this basically means that before such
-             * update, this any object used to have the current resource assigned by more than one mean (for example,
+             * (b) happens when the provided updated entity does have the current resource assigned (when the task
+             * is generated via Logic's update()): this basically means that before such
+             * update, this entity used to have the current resource assigned by more than one mean (for example,
              * two different memberships with the same resource).
              */
             Any<?> any = getAny(task);
@@ -339,9 +352,9 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
                     : any instanceof AnyObject
                             ? anyObjectDAO.findAllResourceNames((AnyObject) any)
                             : any instanceof Group
-                                    ? ((Group) any).getResourceNames()
+                                    ? ((Group) any).getResourceKeys()
                                     : Collections.<String>emptySet();
-            if (!resources.contains(task.getResource().getKey())) {
+            if (task.getAnyTypeKind() == null || !resources.contains(task.getResource().getKey())) {
                 LOG.debug("Delete {} on {}", beforeObj.getUid(), task.getResource().getKey());
 
                 connector.delete(beforeObj.getObjectClass(), beforeObj.getUid(), null, propagationAttempted);
@@ -373,15 +386,21 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         ConnectorObject afterObj = null;
 
         Provision provision = null;
+        OrgUnit orgUnit = null;
         Uid uid = null;
         Connector connector = null;
         Result result;
         try {
             provision = task.getResource().getProvision(new ObjectClass(task.getObjectClassName()));
+            orgUnit = task.getResource().getOrgUnit();
             connector = connFactory.getConnector(task.getResource());
 
             // Try to read remote object BEFORE any actual operation
-            beforeObj = getRemoteObject(task, connector, provision, false);
+            beforeObj = provision == null && orgUnit == null
+                    ? null
+                    : orgUnit == null
+                            ? getRemoteObject(task, connector, provision, false)
+                            : getRemoteObject(task, connector, orgUnit);
 
             for (PropagationActions action : actions) {
                 action.before(task, beforeObj);
@@ -444,7 +463,11 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
                     task.setConnObjectKey(uid.getUidValue());
                 }
                 try {
-                    afterObj = getRemoteObject(task, connector, provision, true);
+                    afterObj = provision == null && orgUnit == null
+                            ? null
+                            : orgUnit == null
+                                    ? getRemoteObject(task, connector, provision, true)
+                                    : getRemoteObject(task, connector, orgUnit);
                 } catch (Exception ignore) {
                     // ignore exception
                     LOG.error("Error retrieving after object", ignore);
@@ -492,22 +515,22 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
 
         notificationManager.createTasks(
                 AuditElements.EventCategoryType.PROPAGATION,
-                task.getAnyTypeKind().name().toLowerCase(),
+                task.getAnyTypeKind() == null ? "realm" : task.getAnyTypeKind().name().toLowerCase(),
                 task.getResource().getKey(),
                 task.getOperation().name().toLowerCase(),
                 result,
-                beforeObj, // searching for before object is too much expensive ... 
+                beforeObj,
                 new Object[] { execution, afterObj },
                 task);
 
         auditManager.audit(
                 AuditElements.EventCategoryType.PROPAGATION,
-                task.getAnyTypeKind().name().toLowerCase(),
+                task.getAnyTypeKind() == null ? "realm" : task.getAnyTypeKind().name().toLowerCase(),
                 task.getResource().getKey(),
                 task.getOperation().name().toLowerCase(),
                 result,
-                connObjectUtils.getConnObjectTO(beforeObj), // searching for before object is too much expensive ... 
-                new Object[] { execution, connObjectUtils.getConnObjectTO(afterObj) },
+                beforeObj,
+                new Object[] { execution, afterObj },
                 task);
 
         return execution;
@@ -606,11 +629,11 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             for (MappingItem item : linkingMappingItems) {
                 Attribute attr = obj.getAttributeByName(item.getExtAttrName());
                 if (attr == null) {
-                    virAttrCache.expire(task.getAnyType(), task.getAnyKey(), item.getIntAttrName());
+                    virAttrCache.expire(task.getAnyType(), task.getEntityKey(), item.getIntAttrName());
                 } else {
                     VirAttrCacheValue cacheValue = new VirAttrCacheValue();
                     cacheValue.setValues(attr.getValue());
-                    virAttrCache.put(task.getAnyType(), task.getAnyKey(), item.getIntAttrName(), cacheValue);
+                    virAttrCache.put(task.getAnyType(), task.getEntityKey(), item.getIntAttrName(), cacheValue);
                 }
             }
         } catch (TimeoutException toe) {
@@ -622,4 +645,44 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
 
         return obj;
     }
+
+    /**
+     * Get remote object for given task.
+     *
+     * @param connector connector facade proxy.
+     * @param task current propagation task.
+     * @param orgUnit orgUnit
+     * @return remote connector object.
+     */
+    protected ConnectorObject getRemoteObject(
+            final PropagationTask task,
+            final Connector connector,
+            final OrgUnit orgUnit) {
+
+        Realm realm = realmDAO.find(task.getEntityKey());
+        if (realm == null) {
+            return null;
+        }
+
+        final ConnectorObject[] obj = new ConnectorObject[1];
+        try {
+            connector.search(new ObjectClass(task.getObjectClassName()),
+                    new EqualsFilter(AttributeBuilder.build(orgUnit.getExtAttrName(), realm.getName())),
+                    new ResultsHandler() {
+
+                @Override
+                public boolean handle(final ConnectorObject connectorObject) {
+                    obj[0] = connectorObject;
+                    return false;
+                }
+            }, new OperationOptionsBuilder().setAttributesToGet(Name.NAME, Uid.NAME, orgUnit.getExtAttrName()).build());
+        } catch (TimeoutException toe) {
+            LOG.debug("Request timeout", toe);
+            throw toe;
+        } catch (RuntimeException ignore) {
+            LOG.debug("While resolving {}", task.getConnObjectKey(), ignore);
+        }
+
+        return obj[0];
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DBPasswordPropagationActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DBPasswordPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DBPasswordPropagationActions.java
index 117722c..88489aa 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DBPasswordPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DBPasswordPropagationActions.java
@@ -57,7 +57,7 @@ public class DBPasswordPropagationActions extends DefaultPropagationActions {
         super.before(task, beforeObj);
 
         if (AnyTypeKind.USER == task.getAnyTypeKind()) {
-            User user = userDAO.find(task.getAnyKey());
+            User user = userDAO.find(task.getEntityKey());
 
             if (user != null && user.getPassword() != null) {
                 Attribute missing = AttributeUtil.find(

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
index 26f7f33..54be326 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
@@ -74,11 +74,11 @@ public class LDAPMembershipPropagationActions extends DefaultPropagationActions
 
         Provision provision = task.getResource().getProvision(anyTypeDAO.findGroup());
         if (AnyTypeKind.USER == task.getAnyTypeKind() && provision != null && provision.getMapping() != null) {
-            User user = userDAO.find(task.getAnyKey());
+            User user = userDAO.find(task.getEntityKey());
             if (user != null) {
                 List<String> groupConnObjectLinks = new ArrayList<>();
                 for (Group group : userDAO.findAllGroups(user)) {
-                    if (group.getResourceNames().contains(task.getResource().getKey())
+                    if (group.getResourceKeys().contains(task.getResource().getKey())
                             && StringUtils.isNotBlank(provision.getMapping().getConnObjectLink())) {
 
                         LOG.debug("Evaluating connObjectLink for {}", group);

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPPasswordPropagationActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPPasswordPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPPasswordPropagationActions.java
index 1447f43..5d5c5b1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPPasswordPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPPasswordPropagationActions.java
@@ -59,7 +59,7 @@ public class LDAPPasswordPropagationActions extends DefaultPropagationActions {
         super.before(task, beforeObj);
 
         if (AnyTypeKind.USER == task.getAnyTypeKind()) {
-            User user = userDAO.find(task.getAnyKey());
+            User user = userDAO.find(task.getEntityKey());
 
             if (user != null && user.getPassword() != null) {
                 Attribute missing = AttributeUtil.find(

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index a0007f1..9bf336e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@ -28,6 +28,9 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.MapContext;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.patch.UserPatch;
@@ -50,11 +53,13 @@ import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 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.resource.OrgUnit;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.MappingManager;
@@ -62,6 +67,7 @@ import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.Name;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -139,9 +145,9 @@ public class PropagationManagerImpl implements PropagationManager {
             final String key,
             final PropagationByResource propByRes,
             final Collection<AttrTO> vAttrs,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
-        return getCreateTasks(find(kind, key), null, null, propByRes, vAttrs, noPropResourceNames);
+        return getCreateTasks(find(kind, key), null, null, propByRes, vAttrs, noPropResourceKeys);
     }
 
     @Override
@@ -151,9 +157,9 @@ public class PropagationManagerImpl implements PropagationManager {
             final Boolean enable,
             final PropagationByResource propByRes,
             final Collection<AttrTO> vAttrs,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
-        return getCreateTasks(userDAO.authFind(key), password, enable, propByRes, vAttrs, noPropResourceNames);
+        return getCreateTasks(userDAO.authFind(key), password, enable, propByRes, vAttrs, noPropResourceKeys);
     }
 
     protected List<PropagationTask> getCreateTasks(
@@ -162,14 +168,14 @@ public class PropagationManagerImpl implements PropagationManager {
             final Boolean enable,
             final PropagationByResource propByRes,
             final Collection<AttrTO> vAttrs,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
         if (propByRes == null || propByRes.isEmpty()) {
             return Collections.<PropagationTask>emptyList();
         }
 
-        if (noPropResourceNames != null) {
-            propByRes.get(ResourceOperation.CREATE).removeAll(noPropResourceNames);
+        if (noPropResourceKeys != null) {
+            propByRes.get(ResourceOperation.CREATE).removeAll(noPropResourceKeys);
         }
 
         return createTasks(any, password, true, enable, false, propByRes, vAttrs);
@@ -183,16 +189,16 @@ public class PropagationManagerImpl implements PropagationManager {
             final Boolean enable,
             final PropagationByResource propByRes,
             final Collection<AttrTO> vAttrs,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
-        return getUpdateTasks(find(kind, key), null, changePwd, enable, propByRes, vAttrs, noPropResourceNames);
+        return getUpdateTasks(find(kind, key), null, changePwd, enable, propByRes, vAttrs, noPropResourceKeys);
     }
 
     @Override
     public List<PropagationTask> getUserUpdateTasks(
             final WorkflowResult<Pair<UserPatch, Boolean>> wfResult,
             final boolean changePwd,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
         return getUpdateTasks(
                 userDAO.authFind(wfResult.getResult().getKey().getKey()),
@@ -203,7 +209,7 @@ public class PropagationManagerImpl implements PropagationManager {
                 wfResult.getResult().getValue(),
                 wfResult.getPropByRes(),
                 wfResult.getResult().getKey().getVirAttrs(),
-                noPropResourceNames);
+                noPropResourceKeys);
     }
 
     @Override
@@ -260,10 +266,10 @@ public class PropagationManagerImpl implements PropagationManager {
             final Boolean enable,
             final PropagationByResource propByRes,
             final Collection<AttrTO> vAttrs,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
-        if (noPropResourceNames != null && propByRes != null) {
-            propByRes.removeAll(noPropResourceNames);
+        if (noPropResourceKeys != null && propByRes != null) {
+            propByRes.removeAll(noPropResourceKeys);
         }
 
         return createTasks(
@@ -281,29 +287,29 @@ public class PropagationManagerImpl implements PropagationManager {
             final AnyTypeKind kind,
             final String key,
             final PropagationByResource propByRes,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
         Any<?> any = find(kind, key);
 
         PropagationByResource localPropByRes = new PropagationByResource();
 
         if (propByRes == null || propByRes.isEmpty()) {
-            localPropByRes.addAll(ResourceOperation.DELETE, any.getResourceNames());
+            localPropByRes.addAll(ResourceOperation.DELETE, any.getResourceKeys());
         } else {
             localPropByRes.merge(propByRes);
         }
 
-        if (noPropResourceNames != null) {
-            localPropByRes.removeAll(noPropResourceNames);
+        if (noPropResourceKeys != null) {
+            localPropByRes.removeAll(noPropResourceKeys);
         }
 
-        return getDeleteTasks(any, localPropByRes, noPropResourceNames);
+        return getDeleteTasks(any, localPropByRes, noPropResourceKeys);
     }
 
     protected List<PropagationTask> getDeleteTasks(
             final Any<?> any,
             final PropagationByResource propByRes,
-            final Collection<String> noPropResourceNames) {
+            final Collection<String> noPropResourceKeys) {
 
         return createTasks(any, null, false, false, true, propByRes, null);
     }
@@ -340,7 +346,7 @@ public class PropagationManagerImpl implements PropagationManager {
         } else if (any instanceof AnyObject) {
             virtualResources.addAll(anyObjectDAO.findAllResourceNames((AnyObject) any));
         } else {
-            virtualResources.addAll(((Group) any).getResourceNames());
+            virtualResources.addAll(((Group) any).getResourceKeys());
         }
 
         Map<String, Set<Attribute>> vAttrMap = new HashMap<>();
@@ -388,12 +394,11 @@ public class PropagationManagerImpl implements PropagationManager {
             } else {
                 PropagationTask task = entityFactory.newEntity(PropagationTask.class);
                 task.setResource(resource);
-                task.setObjectClassName(
-                        resource.getProvision(any.getType()).getObjectClass().getObjectClassValue());
+                task.setObjectClassName(provision.getObjectClass().getObjectClassValue());
                 task.setAnyTypeKind(any.getType().getKind());
                 task.setAnyType(any.getType().getKey());
                 if (!deleteOnResource) {
-                    task.setAnyKey(any.getKey());
+                    task.setEntityKey(any.getKey());
                 }
                 task.setOperation(entry.getValue());
                 task.setOldConnObjectKey(propByRes.getOldConnObjectKey(resource.getKey()));
@@ -441,4 +446,71 @@ public class PropagationManagerImpl implements PropagationManager {
 
         return tasks;
     }
+
+    @Override
+    public List<PropagationTask> createTasks(
+            final Realm realm,
+            final PropagationByResource propByRes,
+            final Collection<String> noPropResourceKeys) {
+
+        if (noPropResourceKeys != null) {
+            propByRes.removeAll(noPropResourceKeys);
+        }
+
+        LOG.debug("Provisioning {}:\n{}", realm, propByRes);
+
+        // Avoid duplicates - see javadoc
+        propByRes.purge();
+        LOG.debug("After purge {}:\n{}", realm, propByRes);
+
+        List<PropagationTask> tasks = new ArrayList<>();
+
+        for (Map.Entry<String, ResourceOperation> entry : propByRes.asMap().entrySet()) {
+            ExternalResource resource = resourceDAO.find(entry.getKey());
+            OrgUnit orgUnit = resource == null ? null : resource.getOrgUnit();
+
+            if (resource == null) {
+                LOG.error("Invalid resource name specified: {}, ignoring...", entry.getKey());
+            } else if (orgUnit == null) {
+                LOG.error("No orgUnit specified on resource {}, ignoring...", resource);
+            } else if (StringUtils.isBlank(orgUnit.getConnObjectLink())) {
+                LOG.warn("Requesting propagation for {} but no ConnObjectLink provided for {}",
+                        realm.getFullPath(), resource);
+            } else {
+                PropagationTask task = entityFactory.newEntity(PropagationTask.class);
+                task.setResource(resource);
+                task.setObjectClassName(orgUnit.getObjectClass().getObjectClassValue());
+                task.setEntityKey(realm.getKey());
+                task.setOperation(entry.getValue());
+
+                Set<Attribute> preparedAttrs = new HashSet<>();
+                preparedAttrs.add(AttributeBuilder.build(orgUnit.getExtAttrName(), realm.getName()));
+
+                JexlContext jexlContext = new MapContext();
+                JexlUtils.addFieldsToContext(realm, jexlContext);
+                String evalConnObjectLink = JexlUtils.evaluate(orgUnit.getConnObjectLink(), jexlContext);
+                if (StringUtils.isBlank(evalConnObjectLink)) {
+                    // add connObjectKey as __NAME__ attribute ...
+                    LOG.debug("Add connObjectKey [{}] as __NAME__", realm.getName());
+                    preparedAttrs.add(new Name(realm.getName()));
+                } else {
+                    LOG.debug("Add connObjectLink [{}] as __NAME__", evalConnObjectLink);
+                    preparedAttrs.add(new Name(evalConnObjectLink));
+
+                    // connObjectKey not propagated: it will be used to set the value for __UID__ attribute
+                    LOG.debug("connObjectKey will be used just as __UID__ attribute");
+                }
+
+                task.setConnObjectKey(realm.getName());
+
+                task.setAttributes(preparedAttrs);
+
+                tasks.add(task);
+
+                LOG.debug("PropagationTask created: {}", task);
+            }
+        }
+
+        return tasks;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/62f56963/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index e8aaacf..8beab31 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -92,7 +92,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
     protected abstract AnyTO doUpdate(AnyTO before, AnyPatch anyPatch, SyncDelta delta, ProvisioningReport result);
 
-    protected void doDeprovision(final AnyTypeKind kind, final String key, final boolean unlink) {
+    protected AnyPatch doDeprovision(final AnyTypeKind kind, final String key, final boolean unlink) {
         PropagationByResource propByRes = new PropagationByResource();
         propByRes.add(ResourceOperation.DELETE, profile.getTask().getResource().getKey());
         taskExecutor.execute(propagationManager.getDeleteTasks(
@@ -101,12 +101,14 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 propByRes,
                 null));
 
+        AnyPatch anyPatch = null;
         if (unlink) {
-            AnyPatch anyObjectPatch = newPatch(key);
-            anyObjectPatch.getResources().add(new StringPatchItem.Builder().
+            anyPatch = newPatch(key);
+            anyPatch.getResources().add(new StringPatchItem.Builder().
                     operation(PatchOperation.DELETE).
                     value(profile.getTask().getResource().getKey()).build());
         }
+        return anyPatch;
     }
 
     protected void doDelete(final AnyTypeKind kind, final String key) {
@@ -442,8 +444,12 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                             }
                         }
 
-                        doDeprovision(provision.getAnyType().getKind(), key, unlink);
-                        output = getAnyTO(key);
+                        AnyPatch anyPatch = doDeprovision(provision.getAnyType().getKind(), key, unlink);
+                        if (anyPatch == null) {
+                            output = getAnyTO(key);
+                        } else {
+                            output = doUpdate(before, anyPatch, delta, result);
+                        }
 
                         for (PullActions action : profile.getActions()) {
                             action.after(profile, delta, AnyTO.class.cast(output), result);
@@ -638,7 +644,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
         return delResults;
     }
 
-    protected List<ProvisioningReport> ignore(
+    protected ProvisioningReport ignore(
             final SyncDelta delta,
             final Provision provision,
             final boolean matching)
@@ -646,7 +652,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         LOG.debug("Any to ignore {}", delta.getObject().getUid().getUidValue());
 
-        final List<ProvisioningReport> ignoreResults = new ArrayList<>();
         ProvisioningReport result = new ProvisioningReport();
 
         result.setKey(null);
@@ -654,7 +659,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
         result.setOperation(ResourceOperation.NONE);
         result.setAnyType(provision.getAnyType().getKey());
         result.setStatus(ProvisioningReport.Status.SUCCESS);
-        ignoreResults.add(result);
 
         if (!profile.isDryRun()) {
             finalize(matching
@@ -662,7 +666,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                     : UnmatchingRule.toEventName(UnmatchingRule.IGNORE), Result.SUCCESS, null, null, delta);
         }
 
-        return ignoreResults;
+        return result;
     }
 
     /**
@@ -717,7 +721,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, provision, false));
+                            profile.getResults().add(ignore(delta, provision, false));
                             break;
 
                         default:
@@ -767,7 +771,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, provision, true));
+                            profile.getResults().add(ignore(delta, provision, true));
                             break;
 
                         default: