You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2014/02/02 19:15:55 UTC

[4/4] git commit: ISIS-661, ISIS-672, ISIS-673: execute background actions via quartz

ISIS-661, ISIS-672, ISIS-673: execute background actions via quartz

ISIS-673
* new AbstractIsisSessionTemplate, similar to Spring's JdbcTemplate etc classes, as an arbitrary 'runnable' against Isis

ISIS-661:
* BackgroundActionExecution
  - using above AbstractIsisSessionTemplate

ISIS-672:
* example usage in todo app, with BackgroundActionExecutionQuartzJob


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

Branch: refs/heads/master
Commit: a8d01a60db29c4b974ba32bd87a1959636dd43f5
Parents: d78f245
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun Feb 2 18:11:25 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun Feb 2 18:11:25 2014 +0000

----------------------------------------------------------------------
 .../BackgroundActionServiceJdoRepository.java   |   4 +-
 .../reifiableaction/ReifiableActionJdo.java     |  13 +-
 .../background/ActionInvocationMemento.java     |  16 ++
 .../background/BackgroundActionService.java     |  16 ++
 .../services/background/BackgroundService.java  |  27 +++-
 .../reifiableaction/ReifiableAction.java        |  18 +++
 .../reifiableaction/ReifiableActionDefault.java |  18 +++
 .../background/BackgroundActionExecution.java   | 152 +++++++++++++++++++
 .../background/BackgroundServiceDefault.java    |  23 ++-
 .../AbstractIsisSessionTemplate.java            |  83 ++++++++++
 .../dom/src/main/java/dom/todo/ToDoItem.java    |   2 +-
 .../java/webapp/scheduler/AbstractIsisJob.java  | 119 ---------------
 .../webapp/scheduler/AbstractIsisQuartzJob.java |  95 ++++++++++++
 .../scheduler/BackgroundActionExecutionJob.java | 149 ------------------
 .../BackgroundActionExecutionQuartzJob.java     |  46 ++++++
 .../webapp/scheduler/quartz-config.xml          |   2 +-
 16 files changed, 497 insertions(+), 286 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/background/BackgroundActionServiceJdoRepository.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/background/BackgroundActionServiceJdoRepository.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/background/BackgroundActionServiceJdoRepository.java
index f71bea0..043c72d 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/background/BackgroundActionServiceJdoRepository.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/background/BackgroundActionServiceJdoRepository.java
@@ -54,10 +54,10 @@ public class BackgroundActionServiceJdoRepository extends AbstractFactoryAndRepo
     }
 
     @Programmatic
-    public List<ReifiableActionJdo> findBackgroundActionsToStart() {
+    public List<ReifiableActionJdo> findBackgroundActionsNotYetStarted() {
         return allMatches(
                 new QueryDefault<ReifiableActionJdo>(ReifiableActionJdo.class, 
-                        "findBackgroundActionsToStart"));
+                        "findBackgroundActionsNotYetStarted"));
     }
     
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/reifiableaction/ReifiableActionJdo.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/reifiableaction/ReifiableActionJdo.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/reifiableaction/ReifiableActionJdo.java
index ca4a15e..2b8789d 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/reifiableaction/ReifiableActionJdo.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/reifiableaction/ReifiableActionJdo.java
@@ -62,7 +62,7 @@ import org.apache.isis.objectstore.jdo.applib.service.Util;
             value="SELECT "
                     + "FROM org.apache.isis.objectstore.jdo.applib.service.reifiableaction.ReifiableActionJdo "
                     + "WHERE transactionId == :transactionId "
-                    + "&& nature == 'USER_INVOCATION'"),
+                    + "&& nature == 'USER_INITIATED'"),
     @javax.jdo.annotations.Query(
             name="findBackgroundActionByTransactionId", language="JDOQL",  
             value="SELECT "
@@ -76,7 +76,7 @@ import org.apache.isis.objectstore.jdo.applib.service.Util;
                     + "WHERE parent == :parent "
                     + "&& nature == 'BACKGROUND'"),
     @javax.jdo.annotations.Query(
-            name="findBackgroundActionsToStart", language="JDOQL",  
+            name="findBackgroundActionsNotYetStarted", language="JDOQL",  
             value="SELECT "
                     + "FROM org.apache.isis.objectstore.jdo.applib.service.reifiableaction.ReifiableActionJdo "
                     + "WHERE nature == 'BACKGROUND' "
@@ -94,7 +94,7 @@ import org.apache.isis.objectstore.jdo.applib.service.Util;
             value="SELECT "
                     + "FROM org.apache.isis.objectstore.jdo.applib.service.reifiableaction.ReifiableActionJdo "
                     + "WHERE completedAt != null "
-                    + "&& nature == 'USER_INVOCATION' "
+                    + "&& nature == 'USER_INITIATED' "
                     + "ORDER BY timestamp DESC")
 })
 @ObjectType("IsisReifiableAction")
@@ -411,19 +411,16 @@ public class ReifiableActionJdo implements ReifiableAction {
 
     /**
      * The date/time at which this interaction completed.
-     * 
-     * <p>
-     * Not part of the applib API, because the default implementation is not persistent
-     * and so cannot be queried "after the fact".  This JDO-specific class is persistent,
-     * and so we can gather this information.
      */
     @javax.jdo.annotations.Persistent
     @javax.jdo.annotations.Column(allowsNull="true")
     @MemberOrder(name="Timings", sequence = "4")
+    @Override
     public Timestamp getCompletedAt() {
         return completedAt;
     }
 
+    @Override
     public void setCompletedAt(final Timestamp completed) {
         this.completedAt = completed;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
index 89e02eb..333362f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
@@ -1,3 +1,19 @@
+/**
+ *  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.isis.applib.services.background;
 
 import java.util.Iterator;

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundActionService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundActionService.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundActionService.java
index 4077208..61ec384 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundActionService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundActionService.java
@@ -1,3 +1,19 @@
+/**
+ *  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.isis.applib.services.background;
 
 import org.apache.isis.applib.services.reifiableaction.ReifiableAction;

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundService.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundService.java
index da27d30..7e7f388 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundService.java
@@ -1,3 +1,19 @@
+/**
+ *  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.isis.applib.services.background;
 
 import java.lang.reflect.Method;
@@ -28,11 +44,14 @@ public interface BackgroundService {
      */
     @Programmatic
     <T> T execute(final T object);
-    
-    @Programmatic
-    ActionInvocationMemento asActionInvocationMemento(Method m, Object domainObject, Object[] args);
 
+    /**
+     * Not API: for framework use only.
+     * @param domainObject
+     * @param args
+     * @return
+     */
     @Programmatic
-    ActionInvocationMemento newActionInvocationMemento(String memento);
+    ActionInvocationMemento asActionInvocationMemento(Method m, Object domainObject, Object[] args);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableAction.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableAction.java b/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableAction.java
index 237b331..8384778 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableAction.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableAction.java
@@ -233,6 +233,24 @@ public interface ReifiableAction extends HasTransactionId {
      */
     public abstract void setStartedAt(Timestamp startedAt);
     
+    
+    // //////////////////////////////////////
+
+    
+    /**
+     * The date/time at which this action completed.
+     */
+    @Disabled
+    public abstract Timestamp getCompletedAt();
+    
+    /**
+     * <b>NOT API</b>: intended to be called only by the framework.
+     * 
+     * <p>
+     * Implementation notes: set when the Isis PersistenceSession is opened.  Uses the applib {@link Clock}.
+     */
+    public abstract void setCompletedAt(Timestamp completedAt);
+
 
     // //////////////////////////////////////
 

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableActionDefault.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableActionDefault.java b/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableActionDefault.java
index ab48611..7622a60 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableActionDefault.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/reifiableaction/ReifiableActionDefault.java
@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import com.google.common.collect.Maps;
 
+import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.reifiableaction.spi.ReifiableActionService;
 import org.apache.isis.applib.util.ObjectContracts;
@@ -149,6 +150,23 @@ public class ReifiableActionDefault implements ReifiableAction {
         this.startedAt = startedAt;
     }
 
+    
+    // //////////////////////////////////////
+    // completedAt (property)
+    // //////////////////////////////////////
+    
+    private Timestamp completedAt;
+
+    @Override
+    public Timestamp getCompletedAt() {
+        return completedAt;
+    }
+
+    @Override
+    public void setCompletedAt(final Timestamp completed) {
+        this.completedAt = completed;
+    }
+
     // //////////////////////////////////////
     // user (property)
     // //////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
new file mode 100644
index 0000000..9fda66f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
@@ -0,0 +1,152 @@
+/**
+ *  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.isis.core.runtime.services.background;
+
+import java.util.List;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.applib.services.background.ActionInvocationMemento;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.reifiableaction.ReifiableAction;
+import org.apache.isis.applib.services.reifiableaction.ReifiableActionContext;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
+import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
+
+/**
+ * Intended to be used as a base class for executing queued up {@link ReifiableAction background action}s.
+ * 
+ * <p>
+ * This implementation uses the {@link #findBackgroundActionsToExecute() hook method} so that it is
+ * independent of the location where the actions have actually been persisted to.
+ */
+public abstract class BackgroundActionExecution extends AbstractIsisSessionTemplate {
+
+    private final MementoServiceDefault mementoService;
+
+    public BackgroundActionExecution() {
+        // same as configured by BackgroundServiceDefault
+        mementoService = new MementoServiceDefault().withNoEncoding();
+    }
+    
+    // //////////////////////////////////////
+
+    
+    protected void doExecute(Object context) {
+        final List<? extends ReifiableAction> findBackgroundActionsToExecute = findBackgroundActionsToExecute(); 
+        for (final ReifiableAction backgroundAction : findBackgroundActionsToExecute) {
+            execute(backgroundAction);
+        }
+    }
+
+    /**
+     * Mandatory hook method
+     */
+    protected abstract List<? extends ReifiableAction> findBackgroundActionsToExecute();
+
+    // //////////////////////////////////////
+
+    
+    private void execute(final ReifiableAction backgroundAction) {
+        try {
+            reifiableActionContext.setReifiableAction(backgroundAction);
+
+            backgroundAction.setStartedAt(Clock.getTimeAsJavaSqlTimestamp());
+            
+            final String memento = backgroundAction.getMemento();
+            final ActionInvocationMemento aim = new ActionInvocationMemento(mementoService, memento);
+            
+            final String actionId = aim.getActionId();
+   
+            final Bookmark targetBookmark = aim.getTarget();
+            final Object targetObject = bookmarkService.lookup(targetBookmark);
+            
+            final ObjectAdapter targetAdapter = adapterFor(targetObject);
+            final ObjectSpecification specification = targetAdapter.getSpecification();
+   
+            final ObjectAction objectAction = findAction(specification, actionId);
+            if(objectAction == null) {
+                throw new Exception("Unknown action '" + actionId + "'");
+            }
+            
+            final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
+            ObjectAdapter resultAdapter = objectAction.execute(targetAdapter, argAdapters);
+            if(resultAdapter != null) {
+                Bookmark resultBookmark = bookmarkService.bookmarkFor(resultAdapter.getObject());
+                backgroundAction.setResult(resultBookmark);
+            }
+
+        } catch (Exception e) {
+            backgroundAction.setException(Throwables.getStackTraceAsString(e));
+        } finally {
+            backgroundAction.setCompletedAt(Clock.getTimeAsJavaSqlTimestamp());
+        }
+    }
+
+    private ObjectAction findAction(final ObjectSpecification specification, final String actionId) {
+        final List<ObjectAction> objectActions = specification.getObjectActions(Contributed.INCLUDED);
+        for (final ObjectAction objectAction : objectActions) {
+            if(objectAction.getIdentifier().toClassAndNameIdentityString().equals(actionId)) {
+                return objectAction;
+            }
+        }
+        return null;
+    }
+
+    private ObjectAdapter[] argAdaptersFor(final ActionInvocationMemento aim) throws ClassNotFoundException {
+        final int numArgs = aim.getNumArgs();
+        final List<ObjectAdapter> argumentAdapters = Lists.newArrayList();
+        for(int i=0; i<numArgs; i++) {
+            final ObjectAdapter argAdapter = argAdapterFor(aim, i);
+            argumentAdapters.add(argAdapter);
+        }
+        return argumentAdapters.toArray(new ObjectAdapter[]{});
+    }
+
+    private ObjectAdapter argAdapterFor(final ActionInvocationMemento aim, int num) throws ClassNotFoundException {
+        final Class<?> argType = aim.getArgType(num);
+        final Object arg = aim.getArg(num, argType);
+        if(arg == null) {
+            return null;
+        }
+        if(Bookmark.class != argType) {
+            return adapterFor(arg);
+        } else {
+            final Bookmark argBookmark = (Bookmark)arg;
+            final RootOid rootOid = RootOidDefault.create(argBookmark);
+            return adapterFor(rootOid);
+        }
+    }
+
+    
+    // //////////////////////////////////////
+
+    @javax.inject.Inject
+    private BookmarkService bookmarkService;
+
+    @javax.inject.Inject
+    private ReifiableActionContext reifiableActionContext;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
index 160c3cf..deea17d 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
@@ -1,3 +1,19 @@
+/**
+ *  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.isis.core.runtime.services.background;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -216,11 +232,14 @@ public class BackgroundServiceDefault implements BackgroundService {
     }
 
 
-    @Override
-    public ActionInvocationMemento newActionInvocationMemento(String mementoStr) {
+    /**
+     * Not API
+     */
+    ActionInvocationMemento newActionInvocationMemento(String mementoStr) {
         return new ActionInvocationMemento(mementoService, mementoStr);
     }
 
+    
     // //////////////////////////////////////
 
     private BookmarkService bookmarkService;

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
new file mode 100644
index 0000000..cc31fc5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
@@ -0,0 +1,83 @@
+/**
+ *  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.isis.core.runtime.sessiontemplate;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.session.IsisSession;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.TransactionalClosureAbstract;
+
+public abstract class AbstractIsisSessionTemplate {
+
+    /**
+     * Sets up an {@link IsisSession} then passes along any calling framework's context. 
+     */
+    public void execute(final AuthenticationSession authSession, final Object context) {
+        try {
+            IsisContext.openSession(authSession);
+            PersistenceSession persistenceSession = getPersistenceSession();
+            persistenceSession.getServicesInjector().injectServicesInto(this);
+            IsisTransactionManager transactionManager = getTransactionManager(persistenceSession);
+            transactionManager.executeWithinTransaction(new TransactionalClosureAbstract() {
+                @Override
+                public void execute() {
+                    doExecute(context);
+                }
+                
+            });
+        } finally {
+            IsisContext.closeSession();
+        }
+    }
+
+    // //////////////////////////////////////
+    
+    /**
+     * Mandatory hook.
+     */
+    protected abstract void doExecute(Object context);
+
+    // //////////////////////////////////////
+
+    protected ObjectAdapter adapterFor(final Object targetObject) {
+        return getAdapterManager().adapterFor(targetObject);
+    }
+    protected ObjectAdapter adapterFor(final RootOid rootOid) {
+        return getAdapterManager().adapterFor(rootOid);
+    }
+    
+    // //////////////////////////////////////
+    
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected IsisTransactionManager getTransactionManager(PersistenceSession persistenceSession) {
+        return persistenceSession.getTransactionManager();
+    }
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 7743243..df0516f 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -617,7 +617,7 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
     @ActionSemantics(Of.IDEMPOTENT)
     @Prototype
     public ToDoItem completeInBackground() {
-        backgroundService.execute(this).slowCompleted(5000);
+        backgroundService.execute(this).slowCompleted(2000);
         container.informUser("Task '" + getDescription() + "' scheduled for completion");
         return this;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisJob.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisJob.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisJob.java
deleted file mode 100644
index 1413ea4..0000000
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisJob.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package webapp.scheduler;
-
-import java.util.List;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-
-import org.quartz.Job;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.runtime.authentication.standard.SimpleSession;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.core.runtime.system.session.IsisSession;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
-
-public abstract class AbstractIsisJob implements Job {
-
-    private boolean executing;
-
-    /**
-     * Sets up an {@link IsisSession} then delegates to the {@link #doExecute(JobExecutionContext) hook}. 
-     */
-    public void execute(final JobExecutionContext context) throws JobExecutionException {
-        final AuthenticationSession authSession = newAuthSession(context);
-        try {
-            if(executing) {
-                return;
-            }
-            executing = true;
-
-            IsisContext.openSession(authSession);
-            PersistenceSession persistenceSession = IsisContext.getPersistenceSession();
-            persistenceSession.getServicesInjector().injectServicesInto(this);
-            IsisTransactionManager transactionManager = persistenceSession.getTransactionManager();
-            transactionManager.executeWithinTransaction(new TransactionalClosure() {
-                
-                @Override
-                public void preExecute() {
-                }
-                
-                @Override
-                public void execute() {
-                    doExecute(context);
-                }
-                
-                @Override
-                public void onSuccess() {
-                }
-                
-                @Override
-                public void onFailure() {
-                }
-            });
-        } finally {
-            executing = false;
-            IsisContext.closeSession();
-        }
-    }
-
-    AuthenticationSession newAuthSession(JobExecutionContext context) {
-        String user = getKey(context, SchedulerConstants.USER_KEY);
-        String rolesStr = getKey(context, SchedulerConstants.ROLES_KEY);
-        String[] roles = Iterables.toArray(
-                Splitter.on(",").split(rolesStr), String.class);
-        return new SimpleSession(user, roles);
-    }
-
-    
-    /**
-     * Mandatory hook.
-     */
-    protected abstract void doExecute(JobExecutionContext context);
-
-    /**
-     * Helper method for benefit of subclasses
-     */
-    protected String getKey(JobExecutionContext context, String key) {
-        return context.getMergedJobDataMap().getString(key);
-    }
-
-    /**
-     * Helper method for benefit of subclasses
-     */
-    protected <T> T getService(Class<T> cls) {
-        List<Object> services = IsisContext.getServices();
-        for (Object service : services) {
-            if(cls.isAssignableFrom(service.getClass())) {
-                return asT(service);
-            }
-        }
-        throw new IllegalArgumentException("No service of type '" + cls.getName() + "' was found");
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T> T asT(Object service) {
-        return (T) service;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisQuartzJob.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisQuartzJob.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisQuartzJob.java
new file mode 100644
index 0000000..fde2085
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/AbstractIsisQuartzJob.java
@@ -0,0 +1,95 @@
+/**
+ *  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 webapp.scheduler;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.runtime.authentication.standard.SimpleSession;
+import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.session.IsisSession;
+
+public class AbstractIsisQuartzJob implements Job {
+
+    public static enum ConcurrentInstancesPolicy {
+        /**
+         * Only a single instance of this job is allowed to run.  
+         * 
+         * <p>
+         * That is, if the job is invoked again before a previous instance has completed, then silently skips.
+         */
+        SINGLE_INSTANCE_ONLY,
+        /**
+         * Multiple instances of this job are allowed to run concurrently.
+         * 
+         * <p>
+         * That is, it is not required for the previous instance of this job to have completed before this one starts.
+         */
+        MULTIPLE_INSTANCES
+    }
+    
+    private final AbstractIsisSessionTemplate isisRunnable;
+
+    private final ConcurrentInstancesPolicy concurrentInstancesPolicy;
+    private boolean executing;
+
+    public AbstractIsisQuartzJob(AbstractIsisSessionTemplate isisRunnable) {
+        this(isisRunnable, ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY);
+    }
+    public AbstractIsisQuartzJob(AbstractIsisSessionTemplate isisRunnable, ConcurrentInstancesPolicy concurrentInstancesPolicy) {
+        this.isisRunnable = isisRunnable;
+        this.concurrentInstancesPolicy = concurrentInstancesPolicy;
+    }
+
+    // //////////////////////////////////////
+
+    /**
+     * Sets up an {@link IsisSession} then delegates to the {@link #doExecute(JobExecutionContext) hook}. 
+     */
+    public void execute(final JobExecutionContext context) throws JobExecutionException {
+        final AuthenticationSession authSession = newAuthSession(context);
+        try {
+            if(concurrentInstancesPolicy == ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY && executing) {
+                return;
+            }
+            executing = true;
+
+            isisRunnable.execute(authSession, context);
+        } finally {
+            executing = false;
+        }
+    }
+
+    AuthenticationSession newAuthSession(JobExecutionContext context) {
+        String user = getKey(context, SchedulerConstants.USER_KEY);
+        String rolesStr = getKey(context, SchedulerConstants.ROLES_KEY);
+        String[] roles = Iterables.toArray(
+                Splitter.on(",").split(rolesStr), String.class);
+        return new SimpleSession(user, roles);
+    }
+
+    String getKey(JobExecutionContext context, String key) {
+        return context.getMergedJobDataMap().getString(key);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionJob.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionJob.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionJob.java
deleted file mode 100644
index bc9dbee..0000000
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionJob.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *
- *  Copyright 2012-2014 Eurocommercial Properties NV
- *
- *
- *  Licensed 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 webapp.scheduler;
-
-import java.util.List;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
-
-import org.quartz.JobExecutionContext;
-
-import org.apache.isis.applib.clock.Clock;
-import org.apache.isis.applib.services.background.ActionInvocationMemento;
-import org.apache.isis.applib.services.background.BackgroundService;
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.services.reifiableaction.ReifiableActionContext;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.objectstore.jdo.applib.service.background.BackgroundActionServiceJdoRepository;
-import org.apache.isis.objectstore.jdo.applib.service.reifiableaction.ReifiableActionJdo;
-
-public class BackgroundActionExecutionJob extends AbstractIsisJob {
-
-    protected void doExecute(JobExecutionContext context) {
-        final BackgroundActionServiceJdoRepository backgroundActionRepo = getService(BackgroundActionServiceJdoRepository.class);
-        final List<ReifiableActionJdo> findBackgroundActionsToStart = backgroundActionRepo.findBackgroundActionsToStart(); 
-        for (final ReifiableActionJdo backgroundAction : findBackgroundActionsToStart) {
-
-            try {
-                reifiableActionContext.setReifiableAction(backgroundAction);
-
-                backgroundAction.setStartedAt(Clock.getTimeAsJavaSqlTimestamp());
-                
-                final String memento = backgroundAction.getMemento();
-                final ActionInvocationMemento aim = backgroundService.newActionInvocationMemento(memento);
-                final String actionId = aim.getActionId();
-    
-                final Bookmark targetBookmark = aim.getTarget();
-                final Object targetObject = bookmarkService.lookup(targetBookmark);
-                
-                final ObjectAdapter targetAdapter = adapterFor(targetObject);
-                final ObjectSpecification specification = targetAdapter.getSpecification();
-    
-                ObjectAction objectAction = findAction(specification, actionId);
-    
-                if(objectAction != null) {
-                    
-                    final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
-                    ObjectAdapter resultAdapter = objectAction.execute(targetAdapter, argAdapters);
-                    if(resultAdapter != null) {
-                        Bookmark resultBookmark = bookmarkService.bookmarkFor(resultAdapter.getObject());
-                        backgroundAction.setResult(resultBookmark);
-                    }
-                }
-
-            } catch (Exception e) {
-                backgroundAction.setException(Throwables.getStackTraceAsString(e));
-            } finally {
-                backgroundAction.setCompletedAt(Clock.getTimeAsJavaSqlTimestamp());
-            }
-
-        }
-    }
-
-    private ObjectAction findAction(final ObjectSpecification specification, final String actionId) {
-        final List<ObjectAction> objectActions = specification.getObjectActions(Contributed.INCLUDED);
-        for (final ObjectAction objectAction : objectActions) {
-            if(objectAction.getIdentifier().toClassAndNameIdentityString().equals(actionId)) {
-                return objectAction;
-            }
-        }
-        return null;
-    }
-
-    private ObjectAdapter[] argAdaptersFor(final ActionInvocationMemento aim) throws ClassNotFoundException {
-        final int numArgs = aim.getNumArgs();
-        final List<ObjectAdapter> argumentAdapters = Lists.newArrayList();
-        for(int i=0; i<numArgs; i++) {
-            final ObjectAdapter argAdapter = argAdapterFor(aim, i);
-            argumentAdapters.add(argAdapter);
-        }
-        return argumentAdapters.toArray(new ObjectAdapter[]{});
-    }
-
-    private ObjectAdapter argAdapterFor(final ActionInvocationMemento aim, int num) throws ClassNotFoundException {
-        final Class<?> argType = aim.getArgType(num);
-        final Object arg = aim.getArg(num, argType);
-        if(arg == null) {
-            return null;
-        } 
-        if(Bookmark.class != argType) {
-            return adapterFor(arg);
-        } 
-        final Bookmark argBookmark = (Bookmark)arg;
-        final RootOid rootOid = RootOidDefault.create(argBookmark);
-        return getAdapterManager().adapterFor(rootOid);
-    }
-
-    private ObjectAdapter adapterFor(final Object targetObject) {
-        return getAdapterManager().adapterFor(targetObject);
-    }
-
-    // //////////////////////////////////////
-
-    
-    protected AdapterManager getAdapterManager() {
-        return getPersistenceSession().getAdapterManager();
-    }
-
-    protected PersistenceSession getPersistenceSession() {
-        return IsisContext.getPersistenceSession();
-    }
-    
-    // //////////////////////////////////////
-
-    
-    @javax.inject.Inject
-    private BackgroundService backgroundService;
-
-    @javax.inject.Inject
-    private BookmarkService bookmarkService;
-
-    @javax.inject.Inject
-    private ReifiableActionContext reifiableActionContext;
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionQuartzJob.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionQuartzJob.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionQuartzJob.java
new file mode 100644
index 0000000..3d6104d
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/scheduler/BackgroundActionExecutionQuartzJob.java
@@ -0,0 +1,46 @@
+/**
+ *  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 webapp.scheduler;
+
+import java.util.List;
+
+import org.apache.isis.applib.services.reifiableaction.ReifiableAction;
+import org.apache.isis.core.runtime.services.background.BackgroundActionExecution;
+import org.apache.isis.objectstore.jdo.applib.service.background.BackgroundActionServiceJdoRepository;
+
+public class BackgroundActionExecutionQuartzJob extends AbstractIsisQuartzJob {
+
+    public BackgroundActionExecutionQuartzJob() {
+        super(new BackgroundActionExecutionFromBackgroundActionServicesJdo());   
+    }
+
+    // //////////////////////////////////////
+
+    public final static class BackgroundActionExecutionFromBackgroundActionServicesJdo extends BackgroundActionExecution {
+
+        @Override
+        protected List<? extends ReifiableAction> findBackgroundActionsToExecute() {
+            return backgroundActionRepository.findBackgroundActionsNotYetStarted(); 
+        }
+        
+        // //////////////////////////////////////
+
+        @javax.inject.Inject
+        private BackgroundActionServiceJdoRepository backgroundActionRepository;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a8d01a60/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/scheduler/quartz-config.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/scheduler/quartz-config.xml b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/scheduler/quartz-config.xml
index df5f4fe..7518e13 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/scheduler/quartz-config.xml
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/resources/webapp/scheduler/quartz-config.xml
@@ -11,7 +11,7 @@ http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
 			<name>BackgroundActionExecutionJob</name>
 			<group>Isis</group>
 			<description>Poll and execute any background actions persisted by the BackgroundActionServiceJdo domain service</description>
-			<job-class>webapp.scheduler.BackgroundActionExecutionJob</job-class>
+			<job-class>webapp.scheduler.BackgroundActionExecutionQuartzJob</job-class>
 			<job-data-map>
 				<entry>
 					<key>webapp.scheduler.user</key>