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>