You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2016/04/13 12:48:19 UTC

syncope git commit: [SYNCOPE-745] Provides notification and integration tests

Repository: syncope
Updated Branches:
  refs/heads/master 1b84ceaa3 -> f1e420a5e


[SYNCOPE-745] Provides notification and integration tests


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

Branch: refs/heads/master
Commit: f1e420a5e1191653a2093c8e9508bcaf808043c0
Parents: 1b84cea
Author: fmartelli <fa...@gmail.com>
Authored: Wed Apr 13 12:47:57 2016 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Wed Apr 13 12:47:57 2016 +0200

----------------------------------------------------------------------
 .../NotificationDirectoryPanel.java             |   8 +-
 .../notifications/NotificationHandler.java      |   8 +-
 .../notifications/NotificationTasks.java        |  28 +++-
 .../console/panels/AnyObjectDirectoryPanel.java |  20 ++-
 .../console/panels/GroupDirectoryPanel.java     |  17 +-
 .../console/panels/UserDirectoryPanel.java      |  17 +-
 .../panels/search/SearchClausePanel.java        |  18 +-
 .../client/console/rest/TaskRestClient.java     |  26 +++
 .../tasks/NotificationTaskDirectoryPanel.java   |  38 ++++-
 .../wicket/markup/html/form/ActionLink.java     |   1 +
 .../markup/html/form/ActionLinksPanel.java      |  28 ++++
 .../notifications/EventSelectionPanel.html      |  24 +--
 .../notifications/LoggerCategoryPanel.html      |   6 +-
 .../console/pages/Notifications.properties      |   3 -
 .../console/pages/Notifications_it.properties   |   3 -
 .../pages/Notifications_pt_BR.properties        |   3 -
 .../console/panels/DirectoryPanel.properties    |   6 +
 .../console/panels/DirectoryPanel_it.properties |   5 +
 .../panels/DirectoryPanel_pt_BR.properties      |   5 +
 .../markup/html/form/ActionLinksPanel.html      |   5 +
 .../core/persistence/jpa/dao/JPATaskDAO.java    |   2 +-
 .../test/resources/domains/MasterContent.xml    |   2 +-
 .../notification/NotificationManagerImpl.java   |  17 +-
 .../src/test/resources/rebel.xml                |   2 +-
 .../fit/console/NotificationsITCase.java        | 165 +++++++++++++++++++
 25 files changed, 394 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
index bca79e1..f35f109 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
@@ -106,13 +106,13 @@ public class NotificationDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final NotificationTO ignore) {
-                        target.add(utilityModal.setContent(new NotificationTasks(
-                                utilityModal, pageRef, model.getObject())));
-                        utilityModal.header(new ResourceModel("notification.executions", "Tasks"));
+                        target.add(utilityModal.setContent(
+                                new NotificationTasks(model.getObject().getKey(), pageRef)));
+                        utilityModal.header(new StringResourceModel("notification.tasks", model));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
-                }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_LIST);
+                }, ActionLink.ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST);
 
                 panel.add(new ActionLink<NotificationTO>() {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationHandler.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationHandler.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationHandler.java
index 274eb13..28f4f26 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationHandler.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationHandler.java
@@ -24,7 +24,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
@@ -53,8 +52,9 @@ public class NotificationHandler implements Serializable {
     public List<Pair<String, List<SearchClause>>> getAboutClauses() {
         if (this.aboutClauses == null) {
             this.aboutClauses = new ArrayList<>();
-            for (Map.Entry<String, String> entry : this.notificationTO.getAbouts().entrySet()) {
-                this.aboutClauses.add(Pair.of(entry.getKey(), SearchUtils.getSearchClauses(entry.getValue())));
+            for (Map.Entry<String, List<SearchClause>> entry
+                    : SearchUtils.getSearchClauses(this.notificationTO.getAbouts()).entrySet()) {
+                this.aboutClauses.add(Pair.of(entry.getKey(), (entry.getValue())));
             }
         }
 
@@ -104,7 +104,7 @@ public class NotificationHandler implements Serializable {
 
     private String getRecipientsFIQL() {
         if (CollectionUtils.isEmpty(this.recipientClauses)) {
-            return StringUtils.EMPTY;
+            return null;
         } else {
             return getFIQLString(this.recipientClauses, SyncopeClient.getUserSearchConditionBuilder());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
index ead48bb..b0f21f5 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
@@ -26,29 +26,51 @@ import org.apache.syncope.client.console.tasks.TaskExecutionDetails;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
 
 public class NotificationTasks extends Panel implements ModalPanel<Serializable> {
 
     private static final long serialVersionUID = 1066124171682570083L;
 
     public NotificationTasks(
-            final BaseModal<?> baseModal, final PageReference pageReference, final NotificationTO notificationTO) {
+            final AnyTypeKind anyTypeKind,
+            final Long anyTypeKey,
+            final PageReference pageReference) {
+        this(null, anyTypeKind, anyTypeKey, pageReference);
+    }
+
+    public NotificationTasks(
+            final Long notification,
+            final PageReference pageReference) {
+        this(notification, null, null, pageReference);
+    }
+
+    private NotificationTasks(
+            final Long notification,
+            final AnyTypeKind anyTypeKind,
+            final Long anyTypeKey,
+            final PageReference pageReference) {
         super(BaseModal.CONTENT_ID);
 
         final MultilevelPanel mlp = new MultilevelPanel("tasks");
         add(mlp);
 
-        mlp.setFirstLevel(new NotificationTaskDirectoryPanel(null, mlp, pageReference) {
+        mlp.setFirstLevel(
+                new NotificationTaskDirectoryPanel(notification, anyTypeKind, anyTypeKey, mlp, pageReference) {
 
             private static final long serialVersionUID = -2195387360323687302L;
 
             @Override
             protected void viewTask(final NotificationTaskTO taskTO, final AjaxRequestTarget target) {
-                mlp.next("task.view", new TaskExecutionDetails<>(null, taskTO, pageReference), target);
+                mlp.next(
+                        new StringResourceModel("task.view", this, new Model<>(taskTO)).getObject(),
+                        new TaskExecutionDetails<>(null, taskTO, pageReference), target);
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
index 7c67ab0..8d786ab 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
@@ -28,6 +28,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
 import org.apache.syncope.client.console.status.StatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
@@ -130,8 +131,8 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO> {
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
-                        final IModel<AnyHandler<AnyObjectTO>> formModel =
-                                new CompoundPropertyModel<>(new AnyHandler<>(model.getObject()));
+                        final IModel<AnyHandler<AnyObjectTO>> formModel = new CompoundPropertyModel<>(new AnyHandler<>(
+                                model.getObject()));
                         altDefaultModal.setFormModel(formModel);
 
                         target.add(altDefaultModal.setContent(new StatusModal<>(
@@ -150,8 +151,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO> {
                     public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
                         send(AnyObjectDirectoryPanel.this, Broadcast.EXACT,
                                 new AjaxWizard.EditItemActionEvent<>(
-                                        new AnyHandler<>(new AnyObjectRestClient().read(model.getObject().
-                                                getKey())),
+                                        new AnyHandler<>(new AnyObjectRestClient().read(model.getObject().getKey())),
                                         target));
                     }
                 }, ActionType.EDIT, AnyEntitlement.READ.getFor(type)).add(new ActionLink<AnyObjectTO>() {
@@ -179,6 +179,18 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO> {
                     }
                 }, ActionType.PROPAGATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<AnyObjectTO>() {
 
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
+                        target.add(utilityModal.setContent(
+                                new NotificationTasks(AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
+                        utilityModal.header(new StringResourceModel("any.notification.tasks", model));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<AnyObjectTO>() {
+
                     private static final long serialVersionUID = -7978723352517770646L;
 
                     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
index 0d1b489..3e0e171 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
@@ -28,6 +28,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.status.StatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
@@ -124,8 +125,8 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO> {
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final GroupTO ignore) {
-                        final IModel<AnyHandler<GroupTO>> formModel =
-                                new CompoundPropertyModel<>(new AnyHandler<>(model.getObject()));
+                        final IModel<AnyHandler<GroupTO>> formModel = new CompoundPropertyModel<>(new AnyHandler<>(
+                                model.getObject()));
                         altDefaultModal.setFormModel(formModel);
 
                         target.add(altDefaultModal.setContent(new StatusModal<>(
@@ -176,6 +177,18 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO> {
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final GroupTO ignore) {
+                        target.add(utilityModal.setContent(
+                                new NotificationTasks(AnyTypeKind.GROUP, model.getObject().getKey(), pageRef)));
+                        utilityModal.header(new StringResourceModel("any.notification.tasks", model));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<GroupTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final GroupTO ignore) {
                         try {
                             restClient.delete(model.getObject().getETagValue(), model.getObject().getKey());
                             info(getString(Constants.OPERATION_SUCCEEDED));

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
index e852764..f2416ea 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
@@ -29,6 +29,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.UserRestClient;
 import org.apache.syncope.client.console.status.StatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
@@ -164,8 +165,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO> {
                     @Override
                     public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
 
-                        final IModel<AnyHandler<UserTO>> formModel =
-                                new CompoundPropertyModel<>(new AnyHandler<>(model.getObject()));
+                        final IModel<AnyHandler<UserTO>> formModel = new CompoundPropertyModel<>(new AnyHandler<>(model.
+                                getObject()));
                         altDefaultModal.setFormModel(formModel);
 
                         target.add(altDefaultModal.setContent(new StatusModal<>(
@@ -236,6 +237,18 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO> {
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                        target.add(utilityModal.setContent(
+                                new NotificationTasks(AnyTypeKind.USER, model.getObject().getKey(), pageRef)));
+                        utilityModal.header(new StringResourceModel("any.notification.tasks", model));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<UserTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
                         try {
                             restClient.delete(model.getObject().getETagValue(), model.getObject().getKey());
                             info(getString(Constants.OPERATION_SUCCEEDED));

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
index 8008119..afe2bcb 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
@@ -376,8 +376,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                         || type.getModelObject() == SearchClause.Type.RELATIONSHIP) {
                     if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
                             || comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
-
-                        value.setModelObject(null);
+                        value.setModelObject(StringUtils.EMPTY);
                         value.setEnabled(false);
                     } else {
                         value.setEnabled(true);
@@ -426,27 +425,30 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                         comparator.setRequired(true);
                     }
 
-                    value.setEnabled(comparator.getModelObject() != SearchClause.Comparator.IS_NULL
-                            && comparator.getModelObject() != SearchClause.Comparator.IS_NOT_NULL);
+                    if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
+                            || comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
+                        value.setEnabled(false);
+                        value.setModelObject(StringUtils.EMPTY);
+                    }
                     property.setChoiceRenderer(new DefaultChoiceRender());
                     break;
 
                 case ROLE_MEMBERSHIP:
                     property.setChoiceRenderer(new DefaultChoiceRender());
                     value.setEnabled(false);
-                    value.setModelObject("");
+                    value.setModelObject(StringUtils.EMPTY);
                     break;
 
                 case GROUP_MEMBERSHIP:
                     property.setChoiceRenderer(new GroupChoiceRender());
                     value.setEnabled(false);
-                    value.setModelObject("");
+                    value.setModelObject(StringUtils.EMPTY);
                     break;
 
                 case RESOURCE:
                     property.setChoiceRenderer(new DefaultChoiceRender());
                     value.setEnabled(false);
-                    value.setModelObject("");
+                    value.setModelObject(StringUtils.EMPTY);
                     break;
 
                 case RELATIONSHIP:
@@ -454,7 +456,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                     if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
                             || comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
                         value.setEnabled(false);
-                        value.setModelObject("");
+                        value.setModelObject(StringUtils.EMPTY);
                         property.setEnabled(true);
                     } else {
                         value.setEnabled(true);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index a7c040f..378269e 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -90,6 +90,32 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
     }
 
     @SuppressWarnings("unchecked")
+    public <T extends AbstractTaskTO> List<T> listNotificationTasks(
+            final Long notification,
+            final AnyTypeKind anyTypeKind,
+            final Long anyTypeKey,
+            final int page,
+            final int size,
+            final SortParam<String> sort) {
+
+        final TaskQuery.Builder builder = new TaskQuery.Builder(TaskType.NOTIFICATION);
+        if (notification != null) {
+            builder.notification(notification);
+        }
+
+        if (anyTypeKind != null) {
+            builder.anyTypeKind(anyTypeKind);
+        }
+
+        if (anyTypeKey != null) {
+            builder.anyTypeKey(anyTypeKey);
+        }
+
+        return (List<T>) getService(TaskService.class).
+                list(builder.page(page).size(size).orderBy(toOrderBy(sort)).build()).getResult();
+    }
+
+    @SuppressWarnings("unchecked")
     public <T extends AbstractTaskTO> List<T> list(
             final Class<T> reference, final int page, final int size, final SortParam<String> sort) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
index 6309e74..d60d507 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
@@ -33,7 +33,6 @@ import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CollectionPropertyColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
@@ -41,6 +40,7 @@ import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
@@ -57,11 +57,22 @@ public abstract class NotificationTaskDirectoryPanel
 
     private static final long serialVersionUID = 4984337552918213290L;
 
+    private final Long notification;
+
+    private final AnyTypeKind anyTypeKind;
+
+    private final Long anyTypeKey;
+
     protected NotificationTaskDirectoryPanel(
-            final BaseModal<?> baseModal,
+            final Long notification,
+            final AnyTypeKind anyTypeKind,
+            final Long anyTypeKey,
             final MultilevelPanel multiLevelPanelRef,
             final PageReference pageRef) {
-        super(baseModal, multiLevelPanelRef, pageRef);
+        super(null, multiLevelPanelRef, pageRef);
+        this.notification = notification;
+        this.anyTypeKind = anyTypeKind;
+        this.anyTypeKey = anyTypeKey;
         initResultTable();
     }
 
@@ -178,7 +189,7 @@ public abstract class NotificationTaskDirectoryPanel
 
     @Override
     protected NotificationTasksProvider dataProvider() {
-        return new NotificationTasksProvider(rows);
+        return new NotificationTasksProvider(notification, anyTypeKind, anyTypeKey, rows);
     }
 
     @Override
@@ -190,16 +201,29 @@ public abstract class NotificationTaskDirectoryPanel
 
         private static final long serialVersionUID = 4725679400450513556L;
 
-        public NotificationTasksProvider(final int paginatorRows) {
+        private final Long notification;
+
+        private final AnyTypeKind anyTypeKind;
+
+        private final Long anyTypeKey;
+
+        public NotificationTasksProvider(
+                final Long notification,
+                final AnyTypeKind anyTypeKind,
+                final Long anyTypeKey,
+                final int paginatorRows) {
             super(paginatorRows, TaskType.PROPAGATION, restClient);
+            this.notification = notification;
+            this.anyTypeKind = anyTypeKind;
+            this.anyTypeKey = anyTypeKey;
         }
 
         @Override
         public Iterator<NotificationTaskTO> iterator(final long first, final long count) {
             final int page = ((int) first / paginatorRows);
 
-            final List<NotificationTaskTO> tasks = restClient.list(
-                    NotificationTaskTO.class, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+            final List<NotificationTaskTO> tasks = restClient.listNotificationTasks(
+                    notification, anyTypeKind, anyTypeKey, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
 
             Collections.sort(tasks, getComparator());
             return tasks.iterator();

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
index c254074..dc4d596 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
@@ -74,6 +74,7 @@ public abstract class ActionLink<T extends Serializable> implements Serializable
         MANAGE_USERS("update"),
         MANAGE_GROUPS("update"),
         PROPAGATION_TASKS("read"),
+        NOTIFICATION_TASKS("read"),
         ZOOM_IN("zoomin"),
         ZOOM_OUT("zoomout");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
index 44b070a..075fc6d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
@@ -85,6 +85,7 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
         super.add(new Fragment("panelDeprovision", "emptyFragment", this));
         super.add(new Fragment("panelProvision", "emptyFragment", this));
         super.add(new Fragment("panelPropagationTasks", "emptyFragment", this));
+        super.add(new Fragment("panelNotificationTasks", "emptyFragment", this));
         super.add(new Fragment("panelZoomIn", "emptyFragment", this));
         super.add(new Fragment("panelZoomOut", "emptyFragment", this));
     }
@@ -733,6 +734,25 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
 
+            case NOTIFICATION_TASKS:
+                fragment = new Fragment("panelNotificationTasks", "fragmentNotificationTasks", this);
+
+                fragment.addOrReplace(new IndicatingAjaxLink<Void>("notificationTasksLink") {
+
+                    private static final long serialVersionUID = -1876519166660008562L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        link.onClick(target, model.getObject());
+                    }
+
+                    @Override
+                    public String getAjaxIndicatorMarkupId() {
+                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                    }
+                }.setVisible(link.isEnabled(model.getObject())));
+                break;
+
             case ZOOM_IN:
                 fragment = new Fragment("panelZoomIn", "fragmentZoomIn", this);
 
@@ -908,6 +928,14 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
                 super.addOrReplace(new Fragment("panelProvision", "emptyFragment", this));
                 break;
 
+            case PROPAGATION_TASKS:
+                super.addOrReplace(new Fragment("panelPropagationTasks", "emptyFragment", this));
+                break;
+
+            case NOTIFICATION_TASKS:
+                super.addOrReplace(new Fragment("panelNotificationTasks", "emptyFragment", this));
+                break;
+
             case ZOOM_IN:
                 super.addOrReplace(new Fragment("panelZoomIn", "emptyFragment", this));
                 break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/notifications/EventSelectionPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/EventSelectionPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/EventSelectionPanel.html
index ae36ca1..8baffa9 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/EventSelectionPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/EventSelectionPanel.html
@@ -24,7 +24,7 @@ under the License.
         width: 100%;
       }
 
-      .labrut {
+      .eventLabel {
         font-size: 12px;
         vertical-align: middle;
         font-family: Verdana,Tahoma,sans-serif;
@@ -33,7 +33,7 @@ under the License.
         height: 20px;
       }
 
-      .divtableheaderlabrut {
+      .divtableheadereventLabel {
         font-weight: bold;
         float: left;
         margin-left: 5px;
@@ -67,13 +67,13 @@ under the License.
     <div class="eventSelectionWidzard">
       <div class="container">
         <div style="display:inline-table;">
-          <div class="labrut">
+          <div class="eventLabel">
             &nbsp;
           </div>
           <div style="display: table-cell">
             <div class="divtableheadercell">
-              <div class="divtableheaderlabrut">
-                <labrut wicket:id="successLabel"/>
+              <div class="divtableheadereventLabel">
+                <eventLabel wicket:id="successLabel"/>
               </div>
               <div style="display: table-cell">
                 <input type="checkbox" wicket:id="successSelector" style="margin-top: 0px;margin-bottom: 0px;"/>
@@ -82,8 +82,8 @@ under the License.
           </div>
           <div style="display: table-cell">
             <div class="divtableheadercell">
-              <div class="divtableheaderlabrut">
-                <labrut wicket:id="failureLabel"/>
+              <div class="divtableheadereventLabel">
+                <eventLabel wicket:id="failureLabel"/>
               </div>
               <div style="display: table-cell">
                 <input type="checkbox" wicket:id="failureSelector" style="margin-top: 0px;margin-bottom: 0px;"/>
@@ -94,9 +94,9 @@ under the License.
       </div>
 
       <div class="container">
-        <div class="labrut">
-          <div id="divtablerow-labrut" wicket:id="categoryView">
-            <div class="labrut">
+        <div class="eventLabel">
+          <div id="divtablerow-eventLabel" wicket:id="categoryView">
+            <div class="eventLabel">
               <span wicket:id="subcategory">[subcategory]</span>
             </div>
           </div>
@@ -105,7 +105,7 @@ under the License.
         <div id="divtablerow-success" class="divtablecheckcolumn">
           <span wicket:id="successGroup">
             <div wicket:id="successView" class="divtablecheck">
-              <div class="divtableheaderlabrut">&nbsp;</div>
+              <div class="divtableheadereventLabel">&nbsp;</div>
               <input type="checkbox" wicket:id="successCheck"/>
             </div>
           </span>
@@ -114,7 +114,7 @@ under the License.
         <div id="divtablerow-failure" class="divtablecheckcolumn">
           <span wicket:id="failureGroup">
             <div wicket:id="failureView" class="divtablecheck">
-              <div class="divtableheaderlabrut">&nbsp;</div>
+              <div class="divtableheadereventLabel">&nbsp;</div>
               <input type="checkbox" wicket:id="failureCheck"/>
             </div>
           </span>

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/notifications/LoggerCategoryPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/LoggerCategoryPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/LoggerCategoryPanel.html
index 3fb3baf..03213b7 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/LoggerCategoryPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/LoggerCategoryPanel.html
@@ -43,7 +43,7 @@ under the License.
         display: table-row;
         width:100%;
       }
-      .eventSelection div#eventElement div#labrut{
+      .eventSelection div#eventElement div#eventLabel{
         display: table-cell;
       }
 
@@ -72,8 +72,8 @@ under the License.
             <span wicket:id="subcategory">[sub-category]</span>
           </div>
           <div>
-            <div id="labrut">
-              <labrut wicket:id="customLabel"/>
+            <div id="eventLabel">
+              <eventLabel wicket:id="customLabel"/>
             </div>
             <div id="value">
               <span wicket:id="custom">[custom]</span>

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
index 22593e0..3456c87 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
@@ -16,16 +16,13 @@
 # under the License.
 notifications=Notifications
 notification.templates=Templates
-notification.executions=Executions
 
-subject=Subject
 sender=Sender
 template=Template
 traceLevel=Trace level
 notification=Notification
 about=About
 events=Events
-recipients=Recipients
 selfAsRecipient=Include users matching About
 recipientAttrType=Recipients e-mail attribute type
 recipientAttrName=Recipients e-mail attribute schema

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
index 9d7fafa..8b8a257 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
@@ -16,16 +16,13 @@
 # under the License.
 notifications=Notifiche
 notification.templates=Template
-notification.executions=Execuzioni
 
-subject=Oggetto
 sender=Mittente
 template=Modello
 traceLevel=Livello di tracciamento
 notification=Notifica
 about=Soggetti
 events=Eventi
-recipients=Destinatari
 selfAsRecipient=Includi i soggetti
 recipientAttrType=Tipo attributo e-mail destinatari
 recipientAttrName=Schema attributo e-mail destinatari

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
index 941d1af..97483b8 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
@@ -16,16 +16,13 @@
 # under the License.
 notifications=Notifica\u00e7\u00f5es
 notification.templates=Template
-notification.executions=Execu\u00e7\u00f5es
 
-subject=Assunto
 sender=Remetente
 template=Template
 traceLevel=N\u00edvel de Trace
 notification=Notifica\u00e7\u00e3o
 about=Sobre
 events=Eventos
-recipients=Destinat\u00e1rios
 selfAsRecipient=Incluir usu\u00e1rios relacionados Sobre
 recipientAttrType=Tipo de atributo de destinat\u00e1rio de email.
 recipientAttrName=Destinat\u00e1rios de e-mail para atributos de esquema

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties
index 7362fcc..76b9809 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties
@@ -30,6 +30,9 @@ creationDate=Creation Date
 tokenValued=Valued
 tokenNotValued=Not valued
 
+subject=Subject
+recipients=Recipients
+
 any.edit=Edit ${anyTO.type} ${anyTO.key}
 any.new=New ${anyTO.type}
 any.finish=Submit ${anyTO.type}
@@ -37,3 +40,6 @@ any.cancel=Cancel ${anyTO.type}
 any.attr.display=Attributes to be displayed
 bulk.action=Bulk action
 any.propagation.tasks=Propagation tasks for ${type} ${key}
+any.notification.tasks=Notification tasks for ${type} ${key}
+notification.tasks=Tasks about notification ${key}
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties
index 58a3558..85961e3 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties
@@ -30,6 +30,9 @@ creationDate=Data Creazione
 tokenValued=Valorizzato
 tokenNotValued=Non valorizzato
 
+subject=Oggetto
+recipients=Destinatari
+
 any.edit=Modifica ${anyTO.type} ${key}
 any.new=Nuovo ${anyTO.type}
 any.attr.display=Attributi da mostrare
@@ -37,3 +40,5 @@ any.finish=Invia ${anyTO.type}
 any.cancel=Annulla ${anyTO.type}
 bulk.action=Operazioni di gruppo
 any.propagation.tasks=Task di propagazione per ${type} ${key}
+any.notification.tasks=Task di notifica per ${type} ${key}
+notification.tasks=Task relativi alla notifica ${key}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties
index 8b5cc59..03119f7 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties
@@ -30,6 +30,9 @@ creationDate=Data de Cria\u00e7\u00e3o
 tokenValued=Atribu\u00eddo
 tokenNotValued=N\u00e3o Atribu\u00eddo
 
+subject=Assunto
+recipients=Destinat\u00e1rios
+
 any.edit=Alterar ${anyTO.type} ${key}
 any.new=Novo ${anyTO.type}
 any.attr.display=Atributos a ser exibido
@@ -37,3 +40,5 @@ any.finish=Apresentar ${anyTO.type}
 any.cancel=Cancelar ${anyTO.type}
 bulk.action=A\u00e7\u00e3o Composta
 any.propagation.tasks=Propagation tasks for ${type} ${key}
+any.notification.tasks=Notification tasks for ${type} ${key}
+notification.tasks=Tasks about notification ${key}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
index 9b1fd08..28ce9e7 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
@@ -47,6 +47,7 @@ under the License.
     <span wicket:id="panelTextEdit">[plus]</span>
     <span wicket:id="panelExport">[plus]</span>
     <span wicket:id="panelPropagationTasks">[plus]</span>
+    <span wicket:id="panelNotificationTasks">[plus]</span>
     <span wicket:id="panelDelete">[plus]</span>
     <span wicket:id="panelSelect">[select]</span>
     <span wicket:id="panelClose">[close]</span>
@@ -134,6 +135,10 @@ under the License.
     <wicket:fragment wicket:id="fragmentPropagationTasks">
       <a href="#" wicket:id="propagationTasksLink" class="btn"><i class="fa fa-arrow-right" alt="PropagationTasks icon" title="PropagationTasks"></i></a>
     </wicket:fragment>
+    
+    <wicket:fragment wicket:id="fragmentNotificationTasks">
+      <a href="#" wicket:id="notificationTasksLink" class="btn"><i class="fa fa-envelope-o" alt="NotificationTasks icon" title="NotificationTasks"></i></a>
+    </wicket:fragment>
 
     <wicket:fragment wicket:id="fragmentDelete">
       <a href="#" wicket:id="deleteLink" class="btn"><i class="glyphicon glyphicon-minus" alt="delete icon" title="Delete"></i></a>

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index aa98a22..95c0c57 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -132,7 +132,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO {
             throw new IllegalArgumentException(type + " is not related to " + ExternalResource.class.getSimpleName());
         }
 
-        if ((anyTypeKind != null || anyKey != null) && type != TaskType.PROPAGATION) {
+        if ((anyTypeKind != null || anyKey != null) && type != TaskType.PROPAGATION && type != TaskType.NOTIFICATION) {
             throw new IllegalArgumentException(type + " is not related to users, groups or any objects");
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 11cd7df..b1ccd34 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -1194,7 +1194,7 @@ $$ }&#10;
   <AnyAbout id="1" anyType_name="USER" notification_id="1" filter="token!=$null"/>
   <Notification_events notification_id="1" event="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
   <Task DTYPE="NotificationTask" id="8" notification_id="1"
-        sender="admin@prova.org" subject="Notification for PULLOPE-81" 
+        sender="admin@prova.org" subject="Notification for SYNCOPE-81" 
         textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
   <NotificationTask_recipients notificationtask_id="8" address="recipient@prova.org"/>  
   

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/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 27a73b6..a16077e 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
@@ -65,8 +65,10 @@ import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 import org.apache.syncope.core.provisioning.api.notification.NotificationRecipientsProvider;
 import org.slf4j.Logger;
@@ -143,6 +145,9 @@ public class NotificationManagerImpl implements NotificationManager {
     private GroupDataBinder groupDataBinder;
 
     @Autowired
+    private AnyObjectDataBinder anyObjectDataBinder;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     @Transactional(readOnly = true)
@@ -201,8 +206,8 @@ public class NotificationManagerImpl implements NotificationManager {
 
         if (notification.getRecipientsProviderClassName() != null) {
             try {
-                NotificationRecipientsProvider recipientsProvider =
-                        (NotificationRecipientsProvider) ApplicationContextProvider.getBeanFactory().
+                NotificationRecipientsProvider recipientsProvider
+                        = (NotificationRecipientsProvider) ApplicationContextProvider.getBeanFactory().
                         createBean(Class.forName(notification.getRecipientsProviderClassName()),
                                 AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
                 recipientEmails.addAll(recipientsProvider.provideRecipients(notification));
@@ -259,18 +264,24 @@ public class NotificationManagerImpl implements NotificationManager {
 
         if (before instanceof UserTO) {
             any = userDAO.find(((UserTO) before).getKey());
+        } else if (output instanceof UserTO) {
+            any = userDAO.find(((UserTO) output).getKey());
         } else if (output instanceof ProvisioningResult
                 && ((ProvisioningResult) output).getAny() instanceof UserTO) {
 
             any = userDAO.find(((ProvisioningResult) output).getAny().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) {
 
             any = anyObjectDAO.find(((ProvisioningResult) output).getAny().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) {
 
@@ -313,6 +324,8 @@ public class NotificationManagerImpl implements NotificationManager {
                         model.put("user", userDataBinder.getUserTO((User) any, true));
                     } else if (any instanceof Group) {
                         model.put("group", groupDataBinder.getGroupTO((Group) any, true));
+                    } else if (any instanceof AnyObject) {
+                        model.put("group", anyObjectDataBinder.getAnyObjectTO((AnyObject) any, true));
                     }
 
                     NotificationTask notificationTask = getNotificationTask(notification, any, model);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/fit/console-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/test/resources/rebel.xml b/fit/console-reference/src/test/resources/rebel.xml
index 9a3b338..c22249f 100644
--- a/fit/console-reference/src/test/resources/rebel.xml
+++ b/fit/console-reference/src/test/resources/rebel.xml
@@ -36,7 +36,7 @@ under the License.
       </dir>
     </link>
     <link target="/">
-      <dir name="${basedir}/../../client/console/target/classes>
+      <dir name="${basedir}/../../client/console/target/classes">
       </dir>
     </link>
     <link target="/">

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1e420a5/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
new file mode 100644
index 0000000..4b079df
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.console;
+
+import static org.junit.Assert.assertNull;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.Notifications;
+import org.apache.wicket.Component;
+import org.apache.wicket.util.tester.FormTester;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class NotificationsITCase extends AbstractConsoleITCase {
+
+    private void createNotification(final String sender, final String subject) {
+        wicketTester.clickLink("body:content:tabbedPanel:panel:container:content:add");
+
+        wicketTester.assertComponent("body:content:tabbedPanel:panel:modal", Modal.class);
+
+        FormTester formTester = wicketTester.newFormTester("body:content:tabbedPanel:panel:modal:form");
+
+        // -------------------------------
+        // generate event to populate recipientAttrName
+        // -------------------------------
+        formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
+        wicketTester.executeAjaxEvent(
+                "body:content:tabbedPanel:panel:modal:form:content:form:view:recipientAttrType:dropDownChoiceField",
+                Constants.ON_CHANGE);
+        // -------------------------------
+
+        formTester.select("content:form:view:recipientAttrType:dropDownChoiceField", 3);
+        formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
+        formTester.setValue("content:form:view:recipientAttrName:dropDownChoiceField", "0");
+        formTester.select("content:form:view:template:dropDownChoiceField", 2);
+        formTester.select("content:form:view:traceLevel:dropDownChoiceField", 0);
+        formTester.setValue("content:form:view:sender:textField", sender);
+        formTester.setValue("content:form:view:subject:textField", subject);
+
+        wicketTester.cleanupFeedbackMessages();
+        formTester.submit("content:form:buttons:next");
+        wicketTester.assertNoErrorMessage();
+
+        formTester = wicketTester.newFormTester("body:content:tabbedPanel:panel:modal:form");
+
+        // -------------------------------
+        // generate event to populate eventsPanel
+        // -------------------------------
+        formTester.setValue("content:form:view:eventSelection:categoryContainer:category:dropDownChoiceField", "0");
+        wicketTester.executeAjaxEvent("body:content:tabbedPanel:panel:modal:form:"
+                + "content:form:view:eventSelection:categoryContainer:category:dropDownChoiceField",
+                Constants.ON_CHANGE);
+        // -------------------------------
+
+        // -------------------------------
+        // select event template
+        // -------------------------------
+        formTester.setValue("content:form:view:eventSelection:eventsContainer:eventsPanel:successGroup", "check0");
+        wicketTester.executeAjaxEvent("body:content:tabbedPanel:panel:modal:form:content:"
+                + "form:view:eventSelection:eventsContainer:eventsPanel:successGroup",
+                Constants.ON_CLICK);
+        // -------------------------------
+
+        formTester.setValue("content:form:view:eventSelection:categoryContainer:category:dropDownChoiceField", "0");
+        formTester.setValue("content:form:view:eventSelection:eventsContainer:eventsPanel:successGroup", "check0");
+
+        wicketTester.cleanupFeedbackMessages();
+        formTester.submit("content:form:buttons:next");
+        wicketTester.assertNoErrorMessage();
+
+        formTester = wicketTester.newFormTester("body:content:tabbedPanel:panel:modal:form");
+        wicketTester.cleanupFeedbackMessages();
+        formTester.submit("content:form:buttons:next");
+        wicketTester.assertNoErrorMessage();
+        wicketTester.assertNoInfoMessage();
+
+        formTester = wicketTester.newFormTester("body:content:tabbedPanel:panel:modal:form");
+        wicketTester.executeAjaxEvent("body:content:tabbedPanel:panel:modal:form:content:form:view:staticRecipients:"
+                + "multiValueContainer:innerForm:content:panelPlus:add", Constants.ON_CLICK);
+        formTester.setValue("content:form:view:staticRecipients:multiValueContainer:innerForm:content:view:0:panel:"
+                + "textField", "recipient@syncope.org");
+        formTester.setValue("content:form:view:selfAsRecipient:checkboxField", true);
+
+        wicketTester.cleanupFeedbackMessages();
+        formTester.submit("content:form:buttons:finish");
+        wicketTester.assertInfoMessages("Operation executed successfully");
+
+        wicketTester.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+    }
+
+    @Before
+    public void login() {
+        doLogin(ADMIN_UNAME, ADMIN_PWD);
+        wicketTester.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+        wicketTester.assertRenderedPage(Notifications.class);
+    }
+
+    @Test
+    public void read() {
+        assertNull(findComponentByProp(KEY, "body:content:tabbedPanel:panel:container:content:searchContainer:"
+                + "resultTable:tablePanel:groupForm:checkgroup:dataTable", 1));
+    }
+
+    @Test
+    public void create() {
+        createNotification("create@syncope.org", "create");
+    }
+
+    @Test
+    public void update() {
+        createNotification("update@syncope.org", "createToUpdate");
+        Component result = findComponentByProp("Subject", "body:content:tabbedPanel:panel:container:content:"
+                + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", "createToUpdate");
+
+        wicketTester.clickLink(
+                result.getPageRelativePath() + ":cells:7:cell:panelEdit:editLink");
+
+        FormTester formTester = wicketTester.newFormTester("body:content:tabbedPanel:panel:modal:form");
+        formTester.submit("content:form:buttons:finish");
+
+        wicketTester.assertInfoMessages("Operation executed successfully");
+        wicketTester.cleanupFeedbackMessages();
+    }
+
+    @Test
+    public void delete() {
+        createNotification("delete@syncope.org", "createToDelete");
+        Component result = findComponentByProp("Subject", "body:content:tabbedPanel:panel:container:content:"
+                + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", "createToDelete");
+
+        wicketTester.getRequest().addParameter("confirm", "true");
+        wicketTester.clickLink(
+                wicketTester.getComponentFromLastRenderedPage(
+                        result.getPageRelativePath() + ":cells:7:cell:panelDelete:deleteLink"));
+
+        wicketTester.executeAjaxEvent(wicketTester.getComponentFromLastRenderedPage(
+                result.getPageRelativePath() + ":cells:7:cell:panelDelete:deleteLink"), "onclick");
+
+        wicketTester.assertInfoMessages("Operation executed successfully");
+        wicketTester.cleanupFeedbackMessages();
+
+        assertNull(findComponentByProp("Subject", "body:content:tabbedPanel:panel:container:content:"
+                + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", "createToDelete"));
+    }
+}