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 2018/03/07 15:27:00 UTC

[2/2] syncope git commit: [SYNCOPE-1280] Jobs are now only attempted to graceful stop, no hard Thread#interrupt any more

[SYNCOPE-1280] Jobs are now only attempted to graceful stop, no hard Thread#interrupt any more


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

Branch: refs/heads/2_0_X
Commit: b0ad3d22e5aafb268bed897459494e197cc44e7b
Parents: 3e4a591
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Mar 7 14:57:01 2018 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Mar 7 16:26:42 2018 +0100

----------------------------------------------------------------------
 .../main/resources/domains/MasterContent.xml    |  8 ---
 .../persistence/jpa/inner/PlainSchemaTest.java  |  2 +-
 .../test/resources/domains/MasterContent.xml    |  8 ---
 .../core/provisioning/api/job/JobDelegate.java  |  4 ++
 .../core/provisioning/api/job/JobManager.java   |  2 -
 .../api/pushpull/SyncopePullExecutor.java       |  4 ++
 .../java/job/AbstractInterruptableJob.java      | 58 ++++----------------
 .../java/job/AbstractSchedTaskJobDelegate.java  | 14 +++++
 .../provisioning/java/job/AfterHandlingJob.java |  9 +--
 .../GroupMemberProvisionTaskJobDelegate.java    | 29 +++++++---
 .../java/job/IdentityRecertification.java       | 18 ++++--
 .../provisioning/java/job/JobManagerImpl.java   |  3 -
 .../java/job/SetUMembershipsJob.java            |  8 +--
 .../java/job/SystemLoadReporterJob.java         |  2 -
 .../core/provisioning/java/job/TaskJob.java     |  2 -
 .../DefaultNotificationJobDelegate.java         | 26 +++++++--
 .../java/job/notification/NotificationJob.java  |  2 -
 .../job/report/DefaultReportJobDelegate.java    | 28 ++++++++--
 .../provisioning/java/job/report/ReportJob.java |  2 -
 .../AbstractProvisioningJobDelegate.java        |  8 ++-
 .../pushpull/AbstractPullResultHandler.java     | 10 ++++
 .../java/pushpull/PullJobDelegate.java          | 12 +++-
 .../java/pushpull/PushJobDelegate.java          | 30 +++++-----
 .../java/pushpull/SchedulingPullActions.java    |  7 ++-
 .../core/reference/TestSampleJobDelegate.java   | 10 ++++
 .../configurationparameters.adoc                |  1 -
 26 files changed, 180 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
index 9d42535..82a59d2 100644
--- a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
@@ -117,14 +117,6 @@ under the License.
   <CPlainAttrValue id="162dd874-0417-4bb9-9724-db1ff2952dd1"
                    attribute_id="9891c0a7-27ee-4215-9eea-ca32e580b4e4" booleanValue="1"/>
 
-  <SyncopeSchema id="tasks.interruptMaxRetries"/>
-  <PlainSchema id="tasks.interruptMaxRetries" type="Long"
-               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CPlainAttr id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db"
-              owner_id="cd64d66f-6fff-4008-b966-a06b1cc1436d" schema_id="tasks.interruptMaxRetries"/>
-  <CPlainAttrValue id="5dc3f4e3-ff9f-4558-a9ac-15336b63a2ad"
-                   attribute_id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db" longValue="20"/>
-  
   <!-- Return hashed password values when reading users -->
   <SyncopeSchema id="return.password.value"/>
   <PlainSchema id="return.password.value" type="Boolean"

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
index dd0fa85..e7407ee 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
@@ -47,7 +47,7 @@ public class PlainSchemaTest extends AbstractTest {
     @Test
     public void findAll() {
         List<PlainSchema> schemas = plainSchemaDAO.findAll();
-        assertEquals(43, schemas.size());
+        assertEquals(42, schemas.size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/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 1c1c8e4..f6c4b90 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -117,14 +117,6 @@ under the License.
   <CPlainAttrValue id="162dd874-0417-4bb9-9724-db1ff2952dd1"
                    attribute_id="9891c0a7-27ee-4215-9eea-ca32e580b4e4" booleanValue="1"/>
 
-  <SyncopeSchema id="tasks.interruptMaxRetries"/>
-  <PlainSchema id="tasks.interruptMaxRetries" type="Long"
-               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CPlainAttr id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db"
-              owner_id="cd64d66f-6fff-4008-b966-a06b1cc1436d" schema_id="tasks.interruptMaxRetries"/>
-  <CPlainAttrValue id="5dc3f4e3-ff9f-4558-a9ac-15336b63a2ad"
-                   attribute_id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db" longValue="20"/>
-  
   <!-- Return hashed password values when reading users -->
   <SyncopeSchema id="return.password.value"/>
   <PlainSchema id="return.password.value" type="Boolean"

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobDelegate.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobDelegate.java
index 3bfa292..1124fb5 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobDelegate.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobDelegate.java
@@ -24,4 +24,8 @@ package org.apache.syncope.core.provisioning.api.job;
 public interface JobDelegate {
 
     String currentStatus();
+
+    void interrupt();
+
+    boolean isInterrupted();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
index 0e327fe..7c36ecb 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
@@ -31,8 +31,6 @@ public interface JobManager {
 
     String DOMAIN_KEY = "domain";
 
-    String INTERRUPT_MAX_RETRIES_KEY = "interruptMaxRetries";
-
     JobKey NOTIFICATION_JOB = new JobKey("notificationJob", Scheduler.DEFAULT_GROUP);
 
     boolean isRunning(JobKey jobKey) throws SchedulerException;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopePullExecutor.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopePullExecutor.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopePullExecutor.java
index 39eed32..f0cc908 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopePullExecutor.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopePullExecutor.java
@@ -27,4 +27,8 @@ public interface SyncopePullExecutor {
     void setLatestSyncToken(ObjectClass objectClass, SyncToken latestSyncToken);
 
     void reportHandled(ObjectClass objectClass, Name name);
+
+    boolean wasInterruptRequested();
+
+    void setInterrupted();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractInterruptableJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractInterruptableJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractInterruptableJob.java
index 86a7f49..b2314c5 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractInterruptableJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractInterruptableJob.java
@@ -18,72 +18,38 @@
  */
 package org.apache.syncope.core.provisioning.java.job;
 
-import java.util.Date;
-import java.util.concurrent.atomic.AtomicReference;
 import org.apache.syncope.core.provisioning.api.job.JobDelegate;
-import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
-import org.apache.syncope.core.provisioning.api.job.JobManager;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.InterruptableJob;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 import org.quartz.UnableToInterruptJobException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @DisallowConcurrentExecution
 public abstract class AbstractInterruptableJob implements InterruptableJob {
 
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractInterruptableJob.class);
-
-    /**
-     * The current running thread containing the task to be executed.
-     */
-    private final AtomicReference<Thread> runningThread = new AtomicReference<>();
-
     private final JobDelegate embeddedDelegate = new JobDelegate() {
 
         @Override
         public String currentStatus() {
-            return "RUNNING THREAD: " + runningThread.get();
+            return "RUNNING";
         }
-    };
 
-    private long interruptMaxRetries = 1;
+        @Override
+        public void interrupt() {
+        }
+
+        @Override
+        public boolean isInterrupted() {
+            return false;
+        }
+
+    };
 
     public JobDelegate getDelegate() {
         return embeddedDelegate;
     }
 
     @Override
-    public void execute(final JobExecutionContext context) throws JobExecutionException {
-        runningThread.set(Thread.currentThread());
-        try {
-            interruptMaxRetries = context.getMergedJobDataMap().getLong(JobManager.INTERRUPT_MAX_RETRIES_KEY);
-        } catch (Exception e) {
-            LOG.debug("Could not set {}, defaults to {}", JobManager.INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries, e);
-        }
-    }
-
-    @Override
     public void interrupt() throws UnableToInterruptJobException {
-        Thread thread = runningThread.getAndSet(null);
-        if (thread == null) {
-            LOG.warn("Unable to retrieve the thread of the current job execution");
-        } else {
-            LOG.info("Interrupting job from thread {} at {} ", thread.getId(), FormatUtils.format(new Date()));
-
-            if (interruptMaxRetries < 1) {
-                interruptMaxRetries = 1;
-            }
-            for (int i = 0; i < interruptMaxRetries && thread.isAlive(); i++) {
-                thread.interrupt();
-            }
-            // if the thread is still alive, it should be available in the next stop
-            if (thread.isAlive()) {
-                runningThread.set(thread);
-            }
-        }
+        getDelegate().interrupt();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
index 7103b7b..3f7e280 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
@@ -75,11 +75,25 @@ public abstract class AbstractSchedTaskJobDelegate implements SchedTaskJobDelega
 
     protected final AtomicReference<String> status = new AtomicReference<>();
 
+    protected boolean interrupt;
+
+    protected boolean interrupted;
+
     @Override
     public String currentStatus() {
         return status.get();
     }
 
+    @Override
+    public void interrupt() {
+        interrupt = true;
+    }
+
+    @Override
+    public boolean isInterrupted() {
+        return interrupted;
+    }
+
     @Transactional
     @Override
     public void execute(final String taskKey, final boolean dryRun, final JobExecutionContext context)

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
index 86a97ca..08ace7d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
@@ -18,8 +18,9 @@
  */
 package org.apache.syncope.core.provisioning.java.job;
 
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
 import java.util.Map;
-import java.util.UUID;
 import org.apache.syncope.core.provisioning.api.AuditManager;
 import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent;
 import org.apache.syncope.core.provisioning.api.job.JobManager;
@@ -49,11 +50,13 @@ public class AfterHandlingJob extends AbstractInterruptableJob {
 
     private static final Logger LOG = LoggerFactory.getLogger(AfterHandlingJob.class);
 
+    private static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator();
+
     public static void schedule(final SchedulerFactoryBean scheduler, final Map<String, Object> jobMap) {
         @SuppressWarnings("unchecked")
         AfterHandlingJob jobInstance = (AfterHandlingJob) ApplicationContextProvider.getBeanFactory().
                 createBean(AfterHandlingJob.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-        String jobName = AfterHandlingJob.class.getName() + UUID.randomUUID();
+        String jobName = AfterHandlingJob.class.getName() + UUID_GENERATOR.generate();
 
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
 
@@ -82,8 +85,6 @@ public class AfterHandlingJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         try {
             AuthContextUtils.execWithAuthContext(context.getMergedJobDataMap().getString(JobManager.DOMAIN_KEY),
                     new AuthContextUtils.Executable<Void>() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/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 4f1a1eb..10d48b9 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
@@ -91,12 +91,13 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
         status.set("About to "
                 + (actionType == BulkMembersActionType.DEPROVISION ? "de" : "") + "provision "
                 + users.size() + " users from " + groupResourceKeys);
-        for (User user : users) {
+
+        for (int i = 0; i < users.size() && !interrupt; i++) {
             List<PropagationStatus> statuses = actionType == BulkMembersActionType.DEPROVISION
-                    ? userProvisioningManager.deprovision(user.getKey(), groupResourceKeys, false)
-                    : userProvisioningManager.provision(user.getKey(), true, null, groupResourceKeys, false);
+                    ? userProvisioningManager.deprovision(users.get(i).getKey(), groupResourceKeys, false)
+                    : userProvisioningManager.provision(users.get(i).getKey(), true, null, groupResourceKeys, false);
             for (PropagationStatus propagationStatus : statuses) {
-                result.append("User ").append(user.getKey()).append('\t').
+                result.append("User ").append(users.get(i).getKey()).append('\t').
                         append("Resource ").append(propagationStatus.getResource()).append('\t').
                         append(propagationStatus.getStatus());
                 if (StringUtils.isNotBlank(propagationStatus.getFailureReason())) {
@@ -106,6 +107,11 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
             }
             result.append("\n");
         }
+        if (interrupt) {
+            LOG.debug("Group assignment interrupted");
+            interrupted = true;
+            return result.append("\n*** Group assignment interrupted ***\n").toString();
+        }
 
         membershipCond = new MembershipCond();
         membershipCond.setGroup(groupKey);
@@ -113,13 +119,15 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
         status.set("About to "
                 + (actionType == BulkMembersActionType.DEPROVISION ? "de" : "") + "provision "
                 + anyObjects.size() + " any objects from " + groupResourceKeys);
-        for (AnyObject anyObject : anyObjects) {
+
+        for (int i = 0; i < anyObjects.size() && !interrupt; i++) {
             List<PropagationStatus> statuses = actionType == BulkMembersActionType.DEPROVISION
-                    ? anyObjectProvisioningManager.deprovision(anyObject.getKey(), groupResourceKeys, false)
-                    : anyObjectProvisioningManager.provision(anyObject.getKey(), groupResourceKeys, false);
+                    ? anyObjectProvisioningManager.deprovision(anyObjects.get(i).getKey(), groupResourceKeys, false)
+                    : anyObjectProvisioningManager.provision(anyObjects.get(i).getKey(), groupResourceKeys, false);
 
             for (PropagationStatus propagationStatus : statuses) {
-                result.append(anyObject.getType().getKey()).append(' ').append(anyObject.getKey()).append('\t').
+                result.append(anyObjects.get(i).getType().getKey()).append(' ').
+                        append(anyObjects.get(i).getKey()).append('\t').
                         append("Resource ").append(propagationStatus.getResource()).append('\t').
                         append(propagationStatus.getStatus());
                 if (StringUtils.isNotBlank(propagationStatus.getFailureReason())) {
@@ -129,6 +137,11 @@ public class GroupMemberProvisionTaskJobDelegate extends AbstractSchedTaskJobDel
             }
             result.append("\n");
         }
+        if (interrupt) {
+            LOG.debug("Group assignment interrupted");
+            interrupted = true;
+            result.append("\n*** Group assignment interrupted ***\n");
+        }
 
         return result.toString();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/IdentityRecertification.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/IdentityRecertification.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/IdentityRecertification.java
index 332af19..3672fac 100755
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/IdentityRecertification.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/IdentityRecertification.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.java.job;
 
+import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
@@ -93,19 +94,24 @@ public class IdentityRecertification extends AbstractSchedTaskJobDelegate {
         status.set("Processing " + total + " users in " + pages + " pages");
 
         long now = System.currentTimeMillis();
-        for (int page = 1; page <= pages; page++) {
+        for (int page = 1; page <= pages && !interrupt; page++) {
             status.set("Processing " + total + " users: page " + page + " of " + pages);
 
-            for (User user : userDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE)) {
-                LOG.debug("Processing user: {}", user.getUsername());
+            List<User> users = userDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE);
+            for (int i = 0; i < users.size() && !interrupt; i++) {
+                LOG.debug("Processing user: {}", users.get(i).getUsername());
 
-                if (StringUtils.isNotBlank(user.getWorkflowId()) && isToBeRecertified(user, now)) {
-                    uwfAdapter.requestCertify(user);
+                if (StringUtils.isNotBlank(users.get(i).getWorkflowId()) && isToBeRecertified(users.get(i), now)) {
+                    uwfAdapter.requestCertify(users.get(i));
                 } else {
-                    LOG.warn("Workflow for {} is null or empty", user);
+                    LOG.warn("Workflow for {} is null or empty", users.get(i));
                 }
             }
         }
+        if (interrupt) {
+            interrupted = true;
+            return "Identity recertification interrupted";
+        }
 
         return "SUCCESS";
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
index 7bd3ad7..b7873cb 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
@@ -241,7 +241,6 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         Map<String, Object> jobMap = new HashMap<>();
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
         jobMap.put(TaskJob.DELEGATE_CLASS_KEY, jobDelegateClassName);
-        jobMap.put(INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries);
 
         registerJob(
                 JobNamer.getJobKey(task).getName(),
@@ -261,7 +260,6 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
 
         Map<String, Object> jobMap = new HashMap<>();
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
-        jobMap.put(INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries);
 
         registerJob(JobNamer.getJobKey(report).getName(), job, report.getCronExpression(), startAt, jobMap);
     }
@@ -378,7 +376,6 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
 
         Map<String, Object> jobMap = new HashMap<>();
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
-        jobMap.put(INTERRUPT_MAX_RETRIES_KEY, conf.getRight());
 
         // 3. NotificationJob
         if (StringUtils.isBlank(conf.getLeft())) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
index 1b509d7..8fe4b67 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
@@ -47,8 +47,6 @@ public class SetUMembershipsJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         try {
             AuthContextUtils.execWithAuthContext(context.getMergedJobDataMap().getString(JobManager.DOMAIN_KEY),
                     new AuthContextUtils.Executable<Void>() {
@@ -68,9 +66,9 @@ public class SetUMembershipsJob extends AbstractInterruptableJob {
                         for (String groupKey : membership.getValue()) {
                             userPatch.getMemberships().add(
                                     new MembershipPatch.Builder().
-                                    operation(PatchOperation.ADD_REPLACE).
-                                    group(groupKey).
-                                    build());
+                                            operation(PatchOperation.ADD_REPLACE).
+                                            group(groupKey).
+                                            build());
                         }
 
                         if (!userPatch.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SystemLoadReporterJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SystemLoadReporterJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SystemLoadReporterJob.java
index 59c195f..dc50398 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SystemLoadReporterJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SystemLoadReporterJob.java
@@ -39,8 +39,6 @@ public class SystemLoadReporterJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         SystemInfo.LoadInstant instant = new SystemInfo.LoadInstant();
 
         instant.setSystemLoadAverage(ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
index d688179..b1a98ca 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
@@ -71,8 +71,6 @@ public class TaskJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         try {
             AuthContextUtils.execWithAuthContext(context.getMergedJobDataMap().getString(JobManager.DOMAIN_KEY),
                     new AuthContextUtils.Executable<Void>() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
index 7ab218b..8279bd2 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
@@ -75,6 +75,10 @@ public class DefaultNotificationJobDelegate implements InitializingBean, Notific
 
     private final AtomicReference<String> status = new AtomicReference<>();
 
+    private boolean interrupt;
+
+    private boolean interrupted;
+
     @Override
     public void afterPropertiesSet() throws Exception {
         if (mailSender instanceof JavaMailSenderImpl) {
@@ -110,6 +114,16 @@ public class DefaultNotificationJobDelegate implements InitializingBean, Notific
         return status.get();
     }
 
+    @Override
+    public void interrupt() {
+        interrupt = true;
+    }
+
+    @Override
+    public boolean isInterrupted() {
+        return interrupted;
+    }
+
     @Transactional
     @Override
     public TaskExec executeSingle(final NotificationTask task) {
@@ -238,10 +252,14 @@ public class DefaultNotificationJobDelegate implements InitializingBean, Notific
 
         status.set("Sending out " + tasks.size() + " notifications");
 
-        for (NotificationTask task : tasks) {
-            LOG.debug("Found notification task {} to be executed: starting...", task);
-            executeSingle(task);
-            LOG.debug("Notification task {} executed", task);
+        for (int i = 0; i < tasks.size() && !interrupt; i++) {
+            LOG.debug("Found notification task {} to be executed: starting...", tasks.get(i));
+            executeSingle(tasks.get(i));
+            LOG.debug("Notification task {} executed", tasks.get(i));
+        }
+        if (interrupt) {
+            LOG.debug("Notification job interrupted");
+            interrupted = true;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJob.java
index 7edcce2..c596740 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJob.java
@@ -62,8 +62,6 @@ public class NotificationJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         LOG.debug("Waking up...");
 
         for (String domain : domainsHolder.getDomains().keySet()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
index a9aeab0..232f93f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Date;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.Deflater;
 import java.util.zip.ZipEntry;
@@ -77,11 +78,25 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
 
     private final AtomicReference<String> status = new AtomicReference<>();
 
+    private boolean interrupt;
+
+    private boolean interrupted;
+
     @Override
     public String currentStatus() {
         return status.get();
     }
 
+    @Override
+    public void interrupt() {
+        interrupt = true;
+    }
+
+    @Override
+    public boolean isInterrupted() {
+        return interrupted;
+    }
+
     @Transactional
     @Override
     public void execute(final String reportKey) throws JobExecutionException {
@@ -145,11 +160,12 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
             status.set("Generating report header");
 
             // iterate over reportlet instances defined for this report
-            for (ReportletConf reportletConf : report.getReportletConfs()) {
+            List<? extends ReportletConf> reportletConfs = report.getReportletConfs();
+            for (int i = 0; i < reportletConfs.size() && !interrupt; i++) {
                 Class<? extends Reportlet> reportletClass =
-                        implementationLookup.getReportletClass(reportletConf.getClass());
+                        implementationLookup.getReportletClass(reportletConfs.get(i).getClass());
                 if (reportletClass == null) {
-                    LOG.warn("Could not find matching reportlet for {}", reportletConf.getClass());
+                    LOG.warn("Could not find matching reportlet for {}", reportletConfs.get(i).getClass());
                 } else {
                     // fetch (or create) reportlet
                     Reportlet reportlet;
@@ -166,7 +182,7 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
                     // invoke reportlet
                     try {
                         status.set("Invoking reportlet " + reportletClass.getName());
-                        reportlet.extract(reportletConf, handler, status);
+                        reportlet.extract(reportletConfs.get(i), handler, status);
                     } catch (Throwable t) {
                         LOG.error("While executing reportlet {} for report {}", reportlet, reportKey, t);
 
@@ -181,6 +197,10 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
                     }
                 }
             }
+            if (interrupt) {
+                LOG.debug("Report job {} interrupted", reportKey);
+                interrupted = true;
+            }
 
             // report footer
             status.set("Generating report footer");

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReportJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReportJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReportJob.java
index 5ef6785..ef1b0a8 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReportJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReportJob.java
@@ -60,8 +60,6 @@ public class ReportJob extends AbstractInterruptableJob {
 
     @Override
     public void execute(final JobExecutionContext context) throws JobExecutionException {
-        super.execute(context);
-
         try {
             AuthContextUtils.execWithAuthContext(context.getMergedJobDataMap().getString(JobManager.DOMAIN_KEY),
                     new AuthContextUtils.Executable<Void>() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractProvisioningJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractProvisioningJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractProvisioningJobDelegate.java
index 671a85a..dab7a85 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractProvisioningJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractProvisioningJobDelegate.java
@@ -44,8 +44,7 @@ import org.apache.syncope.core.provisioning.java.job.TaskJob;
 import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
 
-public abstract class AbstractProvisioningJobDelegate<T extends ProvisioningTask>
-        extends AbstractSchedTaskJobDelegate {
+public abstract class AbstractProvisioningJobDelegate<T extends ProvisioningTask> extends AbstractSchedTaskJobDelegate {
 
     @Resource(name = "adminUser")
     protected String adminUser;
@@ -92,7 +91,10 @@ public abstract class AbstractProvisioningJobDelegate<T extends ProvisioningTask
         StringBuilder report = new StringBuilder();
 
         if (dryRun) {
-            report.append("==>Dry run only, no modifications were made<==\n\n");
+            report.append("==> Dry run only, no modifications were made <==\n\n");
+        }
+        if (interrupted) {
+            report.append("==> Execution was interrupted <==\n\n");
         }
 
         List<ProvisioningReport> rSuccCreate = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/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 ef32fc9..9991330 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
@@ -135,6 +135,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             LOG.debug("Successfully handled {}", delta);
 
             if (profile.getTask().getPullMode() != PullMode.INCREMENTAL) {
+                if (executor.wasInterruptRequested()) {
+                    LOG.debug("Pull interrupted");
+                    executor.setInterrupted();
+                    return false;
+                }
                 return true;
             }
 
@@ -146,6 +151,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             if (shouldContinue) {
                 executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
             }
+            if (executor.wasInterruptRequested()) {
+                LOG.debug("Pull interrupted");
+                executor.setInterrupted();
+                return false;
+            }
             return shouldContinue;
         } catch (IgnoreProvisionException e) {
             ProvisioningReport ignoreResult = new ProvisioningReport();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index dfb526e..6f9eedf 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -105,6 +105,16 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
     }
 
     @Override
+    public boolean wasInterruptRequested() {
+        return interrupt;
+    }
+
+    @Override
+    public void setInterrupted() {
+        this.interrupted = true;
+    }
+
+    @Override
     public String currentStatus() {
         synchronized (status) {
             if (!handled.isEmpty()) {
@@ -112,7 +122,7 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
                 for (Map.Entry<ObjectClass, MutablePair<Integer, String>> entry : handled.entrySet()) {
                     builder.append(' ').append(entry.getValue().getLeft()).append('\t').
                             append(entry.getKey().getObjectClassValue()).
-                            append("\t/ latest: ").append(entry.getValue().getRight()).
+                            append(" / latest: ").append(entry.getValue().getRight()).
                             append('\n');
                 }
                 status.set(builder.toString());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
index abbb765..ae5e669 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
@@ -113,7 +113,7 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
                 for (Map.Entry<String, MutablePair<Integer, String>> entry : handled.entrySet()) {
                     builder.append(' ').append(entry.getValue().getLeft()).append('\t').
                             append(entry.getKey()).
-                            append("\t/ latest: ").append(entry.getValue().getRight()).
+                            append(" / latest: ").append(entry.getValue().getRight()).
                             append('\n');
                 }
                 status.set(builder.toString());
@@ -147,19 +147,19 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
             final ExternalResource resource)
             throws JobExecutionException {
 
-        for (Any<?> any : anys) {
+        for (int i = 0; i < anys.size() && !interrupt; i++) {
             try {
-                handler.handle(any.getKey());
+                handler.handle(anys.get(i).getKey());
                 reportHandled(
-                        any.getType().getKey(),
-                        (any instanceof User
-                                ? ((User) any).getUsername()
-                                : any instanceof Group
-                                        ? ((Group) any).getName()
-                                        : ((AnyObject) any).getName()));
+                        anys.get(i).getType().getKey(),
+                        (anys.get(i) instanceof User
+                        ? ((User) anys.get(i)).getUsername()
+                        : anys.get(i) instanceof Group
+                        ? ((Group) anys.get(i)).getName()
+                        : ((AnyObject) anys.get(i)).getName()));
             } catch (Exception e) {
-                LOG.warn("Failure pushing '{}' on '{}'", any, resource, e);
-                throw new JobExecutionException("While pushing " + any + " on " + resource, e);
+                LOG.warn("Failure pushing '{}' on '{}'", anys.get(i), resource, e);
+                throw new JobExecutionException("While pushing " + anys.get(i) + " on " + resource, e);
             }
         }
     }
@@ -286,7 +286,7 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
                         Collections.singleton(profile.getTask().getSourceRealm().getFullPath()),
                         cond,
                         provision.getAnyType().getKind());
-                for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
+                for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1 && !interrupt; page++) {
                     List<? extends Any<?>> anys = searchDAO.search(
                             Collections.singleton(profile.getTask().getSourceRealm().getFullPath()),
                             cond,
@@ -299,12 +299,16 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
             }
         }
 
-        if (!profile.isDryRun()) {
+        if (!profile.isDryRun() && !interrupt) {
             for (PushActions action : actions) {
                 action.afterAll(profile);
             }
         }
 
+        if (interrupt) {
+            interrupted = true;
+        }
+
         status.set("Push done");
 
         String result = createReport(profile.getResults(), pushTask.getResource(), dryRun);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
index 841b226..cd380da 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
@@ -18,8 +18,9 @@
  */
 package org.apache.syncope.core.provisioning.java.pushpull;
 
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
 import java.util.Map;
-import java.util.UUID;
 import org.apache.syncope.core.provisioning.api.job.JobManager;
 import org.apache.syncope.core.provisioning.api.job.JobNamer;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
@@ -42,6 +43,8 @@ import org.springframework.scheduling.quartz.SchedulerFactoryBean;
  */
 public abstract class SchedulingPullActions extends DefaultPullActions {
 
+    private static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator();
+
     @Autowired
     protected SchedulerFactoryBean scheduler;
 
@@ -51,7 +54,7 @@ public abstract class SchedulingPullActions extends DefaultPullActions {
         @SuppressWarnings("unchecked")
         T jobInstance = (T) ApplicationContextProvider.getBeanFactory().
                 createBean(reference, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-        String jobName = getClass().getName() + UUID.randomUUID();
+        String jobName = getClass().getName() + UUID_GENERATOR.generate();
 
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSampleJobDelegate.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSampleJobDelegate.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSampleJobDelegate.java
index b1f106e..ce6d940 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSampleJobDelegate.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSampleJobDelegate.java
@@ -49,7 +49,17 @@ public class TestSampleJobDelegate extends AbstractSchedTaskJobDelegate {
     }
 
     @Override
+    public void interrupt() {
+    }
+
+    @Override
+    public boolean isInterrupted() {
+        return false;
+    }
+
+    @Override
     protected boolean hasToBeRegistered(final TaskExec execution) {
         return true;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b0ad3d22/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/configurationparameters.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/configurationparameters.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/configurationparameters.adoc
index 71867f3..6a8a468 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/configurationparameters.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/configurationparameters.adoc
@@ -49,7 +49,6 @@ mechanism to work properly;
 [WARNING]
 Suspended Users are anyway not allowed to authenticate.
 * `log.lastlogindate` - whether the system updates the `lastLoginDate` field of users upon authentication;
-* `tasks.interruptMaxRetries` - how many attempts shall be made when interrupting a running <<task,task>>;
 * `return.password.value` - whether the hashed password value shall be returned when reading users;
 * `identity.recertification.day.interval` - number of days between
 <<identity-recertification,identity recertifications>>;