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 2018/02/02 16:31:45 UTC
[isis] branch maint-1.16.1 updated: ISIS-1569: refactors for
different implementation of replay
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/maint-1.16.1 by this push:
new 7585283 ISIS-1569: refactors for different implementation of replay
7585283 is described below
commit 7585283a6b66f30960642bc0863052d4398fbaec
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Feb 2 16:21:22 2018 +0000
ISIS-1569: refactors for different implementation of replay
specifically:
- factors out CommandExecutionAbstract from BackgroundCommandExecution, and simplifies the latter (removes concept of an OnExceptionPolicy previously introduced)
- Command#executeIn no longer overloaded to hold state (CommandJdo introduces replayState, not part of API)
- introduces new CommandDtoProcessorService SPI to globally postprocess CommandDto's; dogfood this within ContentMappingServiceForCommandDto (copying over details)
also
- removes legacy support within BackgroundCommandExecution/CommandExecutionAbstract
- made some methods of AbstractIsisSessionTemplate final
- lets SimpleSession be subclassable
- allows Clock to be replaceable always
---
.../org/apache/isis/applib/annotation/Command.java | 10 +-
.../java/org/apache/isis/applib/clock/Clock.java | 12 +-
.../conmap/ContentMappingServiceForCommandDto.java | 102 ++--
.../ContentMappingServiceForCommandsDto.java | 7 +-
.../conmap/spi/CommandDtoProcessorService.java | 38 ++
.../authentication/standard/SimpleSession.java | 2 +-
.../background/BackgroundCommandExecution.java | 512 +--------------------
...xecution.java => CommandExecutionAbstract.java} | 274 +++--------
.../AbstractIsisSessionTemplate.java | 8 +-
9 files changed, 195 insertions(+), 770 deletions(-)
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Command.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Command.java
index 1defbbb..39cc97f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Command.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Command.java
@@ -87,19 +87,11 @@ public @interface Command {
* @deprecated - use {@link CommandExecuteIn#REPLAYABLE}
*/
@Deprecated
- REPLAYABLE,
- /**
- * For framework use, not intended to be used in application code.
- *
- * @deprecated - use {@link CommandExecuteIn#EXCLUDED}
- */
- @Deprecated
- EXCLUDED;
+ REPLAYABLE;
public boolean isForeground() { return this == FOREGROUND; }
public boolean isBackground() { return this == BACKGROUND; }
public boolean isReplayable() { return this == REPLAYABLE; }
- public boolean isExcluded() { return this == EXCLUDED; }
}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java b/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
index 90ae270..cd7c6c9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
@@ -29,7 +29,6 @@ import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.apache.isis.applib.Defaults;
-import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.fixtures.FixtureClock;
/**
@@ -50,7 +49,6 @@ import org.apache.isis.applib.fixtures.FixtureClock;
*/
public abstract class Clock {
protected static Clock instance;
- private static boolean isReplaceable = true;
/**
* Returns the (singleton) instance of {@link Clock}.
@@ -65,7 +63,6 @@ public abstract class Clock {
public final static Clock getInstance() {
if (!isInitialized()) {
instance = new SystemClock();
- isReplaceable = false;
}
return instance;
}
@@ -126,11 +123,6 @@ public abstract class Clock {
return new DateTime(getTime(), Defaults.getTimeZone());
}
- private static void ensureReplaceable() {
- if (!isReplaceable && instance != null) {
- throw new RecoverableException("Clock already set up");
- }
- }
public static Timestamp getTimeAsJavaSqlTimestamp() {
return new java.sql.Timestamp(getTimeAsDateTime().getMillis());
@@ -142,7 +134,6 @@ public abstract class Clock {
* @return whether a clock was removed.
*/
protected static boolean remove() {
- ensureReplaceable();
if (instance == null) {
return false;
}
@@ -151,7 +142,6 @@ public abstract class Clock {
}
protected Clock() {
- ensureReplaceable();
instance = this;
}
@@ -174,6 +164,8 @@ public abstract class Clock {
}
final class SystemClock extends Clock {
+
+ SystemClock() {}
@Override
protected long time() {
return System.currentTimeMillis();
diff --git a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
index a11b9d3..00f7541 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
@@ -27,7 +27,9 @@ import javax.ws.rs.core.MediaType;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.conmap.spi.CommandDtoProcessorService;
import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.CommandDtoProcessor;
import org.apache.isis.applib.services.command.CommandWithDto;
import org.apache.isis.applib.services.metamodel.MetaModelService5;
@@ -49,7 +51,7 @@ public class ContentMappingServiceForCommandDto implements ContentMappingService
return null;
}
- return asProcessedDto(object, metaModelService);
+ return asProcessedDto(object);
}
/**
@@ -57,27 +59,30 @@ public class ContentMappingServiceForCommandDto implements ContentMappingService
*/
@Programmatic
public CommandDto map(final CommandWithDto commandWithDto) {
- return asProcessedDto(commandWithDto, metaModelService);
+ return asProcessedDto(commandWithDto);
}
- static CommandDto asProcessedDto(
- final Object object,
- final MetaModelService5 metaModelService) {
-
+ CommandDto asProcessedDto(final Object object) {
if (!(object instanceof CommandWithDto)) {
return null;
}
final CommandWithDto commandWithDto = (CommandWithDto) object;
- return asProcessedDto(commandWithDto, metaModelService);
+ return asProcessedDto(commandWithDto);
}
- private static CommandDto asProcessedDto(
- CommandWithDto commandWithDto,
- final MetaModelService5 metaModelService) {
- final CommandDto commandDto = commandWithDto.asDto();
+ private CommandDto asProcessedDto(final CommandWithDto commandWithDto) {
+ CommandDto commandDto = commandWithDto.asDto();
- copyOver(commandWithDto, commandDto);
+ // global processors
+ for (final CommandDtoProcessorService commandDtoProcessorService : commandDtoProcessorServices) {
+ commandDto = commandDtoProcessorService.process(commandWithDto, commandDto);
+ if(commandDto == null) {
+ // any processor could return null, effectively breaking the chain.
+ return null;
+ }
+ }
+ // specific processors for this specific member (action or property)
final CommandDtoProcessor commandDtoProcessor =
metaModelService.commandDtoProcessorFor(commandDto.getMember().getLogicalMemberIdentifier());
if (commandDtoProcessor == null) {
@@ -86,39 +91,58 @@ public class ContentMappingServiceForCommandDto implements ContentMappingService
return commandDtoProcessor.process(commandWithDto, commandDto);
}
- private static void copyOver(final CommandWithDto commandWithDto, final CommandDto commandDto) {
- // for some reason this isn't being persisted initially, so patch it in. TODO: should fix this
- commandDto.setUser(commandWithDto.getUser());
+ /**
+ * Uses the SPI infrastructure to copy over standard properties from {@link Command} to {@link CommandDto}.
+ */
+ @DomainService(
+ nature = NatureOfService.DOMAIN,
+ // specify quite a high priority since custom processors will probably want to run after this one
+ // (but can choose to run before if they wish)
+ menuOrder = "1000"
+ )
+ public static class CopyOverFromCommand implements CommandDtoProcessorService {
+
+ public CommandDto process(final Command command, CommandDto commandDto) {
+
+ // for some reason this isn't being persisted initially, so patch it in. TODO: should fix this
+ commandDto.setUser(command.getUser());
+
+ // the timestamp field was only introduced in v1.4 of cmd.xsd, so there's no guarantee
+ // it will have been populated. We therefore copy the value in from CommandWithDto entity.
+ if(commandDto.getTimestamp() == null) {
+ final Timestamp timestamp = command.getTimestamp();
+ commandDto.setTimestamp(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+ }
+
+ CommandDtoUtils.setUserData(commandDto,
+ CommandWithDto.USERDATA_KEY_TARGET_CLASS, command.getTargetClass());
+ CommandDtoUtils.setUserData(commandDto,
+ CommandWithDto.USERDATA_KEY_TARGET_ACTION, command.getTargetAction());
+ CommandDtoUtils.setUserData(commandDto,
+ CommandWithDto.USERDATA_KEY_ARGUMENTS, command.getArguments());
+
+ final Bookmark result = command.getResult();
+ CommandDtoUtils.setUserData(commandDto,
+ CommandWithDto.USERDATA_KEY_RETURN_VALUE, result != null ? result.toString() : null);
+ // knowing whether there was an exception is on the master is used to determine whether to
+ // continue when replayed on the slave if an exception occurs there also
+ CommandDtoUtils.setUserData(commandDto,
+ CommandWithDto.USERDATA_KEY_EXCEPTION, command.getException());
+
+ PeriodDto timings = CommandDtoUtils.timingsFor(commandDto);
+ timings.setStartedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(command.getStartedAt()));
+ timings.setCompletedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(command.getCompletedAt()));
- // the timestamp field was only introduced in v1.4 of cmd.xsd, so there's no guarantee
- // it will have been populated. We therefore copy the value in from CommandWithDto entity.
- if(commandDto.getTimestamp() == null) {
- final Timestamp timestamp = commandWithDto.getTimestamp();
- commandDto.setTimestamp(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+ return commandDto;
}
-
- CommandDtoUtils.setUserData(commandDto,
- CommandWithDto.USERDATA_KEY_TARGET_CLASS, commandWithDto.getTargetClass());
- CommandDtoUtils.setUserData(commandDto,
- CommandWithDto.USERDATA_KEY_TARGET_ACTION, commandWithDto.getTargetAction());
- CommandDtoUtils.setUserData(commandDto,
- CommandWithDto.USERDATA_KEY_ARGUMENTS, commandWithDto.getArguments());
-
- final Bookmark result = commandWithDto.getResult();
- CommandDtoUtils.setUserData(commandDto,
- CommandWithDto.USERDATA_KEY_RETURN_VALUE, result != null ? result.toString() : null);
- // knowing whether there was an exception is on the master is used to determine whether to
- // continue when replayed on the slave if an exception occurs there also
- CommandDtoUtils.setUserData(commandDto,
- CommandWithDto.USERDATA_KEY_EXCEPTION, commandWithDto.getException());
-
- PeriodDto timings = CommandDtoUtils.timingsFor(commandDto);
- timings.setStartedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(commandWithDto.getStartedAt()));
- timings.setCompletedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(commandWithDto.getCompletedAt()));
}
+
@Inject
MetaModelService5 metaModelService;
+ @Inject
+ List<CommandDtoProcessorService> commandDtoProcessorServices;
+
}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandsDto.java b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandsDto.java
index 4ba434e..95ba22a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandsDto.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandsDto.java
@@ -81,11 +81,14 @@ public class ContentMappingServiceForCommandsDto implements ContentMappingServic
return new CommandsDto();
}
- private static CommandDto asDto(final Object object, MetaModelService5 metaModelService5) {
- return ContentMappingServiceForCommandDto.asProcessedDto(object, metaModelService5);
+ private CommandDto asDto(final Object object, MetaModelService5 metaModelService5) {
+ return contentMappingServiceForCommandDto.asProcessedDto(object);
}
@Inject
MetaModelService5 metaModelService5;
+ @Inject
+ ContentMappingServiceForCommandDto contentMappingServiceForCommandDto;
+
}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/conmap/spi/CommandDtoProcessorService.java b/core/applib/src/main/java/org/apache/isis/applib/conmap/spi/CommandDtoProcessorService.java
new file mode 100644
index 0000000..4fe8c69
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/conmap/spi/CommandDtoProcessorService.java
@@ -0,0 +1,38 @@
+/*
+ * 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.conmap.spi;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.conmap.ContentMappingServiceForCommandDto;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
+import org.apache.isis.schema.cmd.v1.CommandDto;
+
+/**
+ * Optional SPI called by {@link ContentMappingServiceForCommandDto}.
+ *
+ * Similar to {@link CommandDtoProcessor}, but applied to all {@link CommandDto}s globally.
+ */
+public interface CommandDtoProcessorService {
+
+ @Programmatic
+ CommandDto process(final Command command, CommandDto commandDto);
+
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/SimpleSession.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/SimpleSession.java
index ca6e8c4..8e5c416 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/SimpleSession.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/SimpleSession.java
@@ -26,7 +26,7 @@ import java.util.List;
import org.apache.isis.core.commons.authentication.AuthenticationSessionAbstract;
import org.apache.isis.core.commons.encoding.DataInputExtended;
-public final class SimpleSession extends AuthenticationSessionAbstract {
+public class SimpleSession extends AuthenticationSessionAbstract {
private static final long serialVersionUID = 1L;
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
index 9127933..f42bd6c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
@@ -16,56 +16,17 @@
*/
package org.apache.isis.core.runtime.services.background;
-import java.sql.Timestamp;
-import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
-import com.google.common.base.Function;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.isis.applib.services.background.ActionInvocationMemento;
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkService2;
-import org.apache.isis.applib.services.clock.ClockService;
import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.Command.Executor;
-import org.apache.isis.applib.services.command.CommandWithDto;
-import org.apache.isis.applib.services.iactn.Interaction;
-import org.apache.isis.applib.services.iactn.InteractionContext;
-import org.apache.isis.applib.services.jaxb.JaxbService;
-import org.apache.isis.applib.services.sudo.SudoService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
-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.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
-import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosureWithReturn;
-import org.apache.isis.schema.cmd.v1.ActionDto;
-import org.apache.isis.schema.cmd.v1.CommandDto;
-import org.apache.isis.schema.cmd.v1.MemberDto;
-import org.apache.isis.schema.cmd.v1.ParamDto;
-import org.apache.isis.schema.cmd.v1.ParamsDto;
-import org.apache.isis.schema.cmd.v1.PropertyDto;
-import org.apache.isis.schema.common.v1.InteractionType;
-import org.apache.isis.schema.common.v1.OidDto;
-import org.apache.isis.schema.common.v1.OidsDto;
-import org.apache.isis.schema.common.v1.ValueWithTypeDto;
-import org.apache.isis.schema.utils.CommandDtoUtils;
-import org.apache.isis.schema.utils.CommonDtoUtils;
/**
* Intended to be used as a base class for executing queued up {@link Command background action}s.
@@ -74,55 +35,19 @@ import org.apache.isis.schema.utils.CommonDtoUtils;
* This implementation uses the {@link #findBackgroundCommandsToExecute() hook method} so that it is
* independent of the location where the actions have actually been persisted to.
*/
-public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemplate {
+public abstract class BackgroundCommandExecution extends CommandExecutionAbstract {
private final static Logger LOG = LoggerFactory.getLogger(BackgroundCommandExecution.class);
- public enum OnExceptionPolicy {
- /**
- * For example, regular background commands.
- */
- CONTINUE,
- /**
- * For example, replayable commands.
- *
- * To be precise, replay will quit only if there is an exception on the slave where there
- * was none on the master. Put another way, a replicated command that failed on the master
- * will not cause the slave to stop executing if it caused an exception.
- */
- QUIT,
- }
-
- public enum SudoPolicy {
- /**
- * For example, regular background commands.
- */
- NO_SWITCH,
- /**
- * For example, replayable commands.
- */
- SWITCH,
- }
-
- private final MementoServiceDefault mementoService;
- private final OnExceptionPolicy onExceptionPolicy;
- private final SudoPolicy sudoPolicy;
-
/**
* Defaults to the historical defaults * for running background commands.
*/
public BackgroundCommandExecution() {
- this(OnExceptionPolicy.CONTINUE, SudoPolicy.NO_SWITCH);
+ this(SudoPolicy.NO_SWITCH);
}
- public BackgroundCommandExecution(
- final OnExceptionPolicy onExceptionPolicy,
- final SudoPolicy sudoPolicy) {
- this.onExceptionPolicy = onExceptionPolicy;
- this.sudoPolicy = sudoPolicy;
-
- // same as configured by BackgroundServiceDefault
- mementoService = new MementoServiceDefault().withNoEncoding();
+ public BackgroundCommandExecution(final SudoPolicy sudoPolicy) {
+ super(sudoPolicy);
}
// //////////////////////////////////////
@@ -140,15 +65,10 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
}
});
- LOG.debug("{}: Found {} to execute", getClass().getName(), commands.size());
+ LOG.debug("Found {} to execute", commands.size());
for (final Command command : commands) {
-
- final boolean shouldContinue = execute(transactionManager, command);
- if(!shouldContinue) {
- LOG.info("NOT continuing to process any further commands, quitting execution");
- return;
- }
+ execute(transactionManager, command);
}
}
@@ -157,425 +77,5 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
*/
protected abstract List<? extends Command> findBackgroundCommandsToExecute();
- // //////////////////////////////////////
-
- /**
- * @return - whether to process any further commands.
- */
- private boolean execute(
- final IsisTransactionManager transactionManager,
- final Command command) {
-
- try {
- return executeCommandWithinTran(transactionManager, command);
- } catch (final RuntimeException ex) {
-
- // attempting to commit the xactn itself could cause an issue
- // so we need extra exception handling here, it seems.
-
- org.apache.isis.applib.annotation.Command.ExecuteIn executeIn = command.getExecuteIn();
- LOG.warn("Exception when committing for: {} {}", executeIn, command.getMemberIdentifier(), ex);
-
- //
- // the previous transaction will have been aborted as part of the recovery handling within
- // TransactionManager's executeCommandWithinTran
- //
- // we therefore start a new xactn in order to make sure that this background command is marked as a failure
- // so it won't be attempted again.
- //
- transactionManager.executeWithinTransaction(new TransactionalClosure(){
- @Override
- public void execute() {
-
- final Interaction backgroundInteraction = interactionContext.getInteraction();
- final Interaction.Execution currentExecution = backgroundInteraction.getCurrentExecution();
- command.setStartedAt(
- currentExecution != null
- ? currentExecution.getStartedAt()
- : clockService.nowAsJavaSqlTimestamp());
-
- command.setCompletedAt(clockService.nowAsJavaSqlTimestamp());
- command.setException(Throwables.getStackTraceAsString(ex));
- }
- });
-
- return determineIfContinue(ex);
- }
- }
-
- /**
- * @return - whether to process any further commands.
- */
- private Boolean executeCommandWithinTran(
- final IsisTransactionManager transactionManager,
- final Command command) {
-
- return transactionManager.executeWithinTransaction(
- command,
- new TransactionalClosureWithReturn<Boolean>() {
- @Override
- public Boolean execute() {
-
- return executeCommandPerSudoPolicy(transactionManager, command);
- }
- });
- }
-
- /**
- * @return - whether to process any further commands.
- */
- private Boolean executeCommandPerSudoPolicy(
- final IsisTransactionManager transactionManager,
- final Command command) {
-
- switch (sudoPolicy) {
- case NO_SWITCH:
- return executeCommand(transactionManager, command);
- case SWITCH:
- final String user = command.getUser();
- return sudoService.sudo(user, new Callable<Boolean>() {
- @Override
- public Boolean call() {
- return executeCommand(transactionManager, command);
- }
- });
- default:
- throw new IllegalStateException("Unrecognized sudoPolicy: " + sudoPolicy);
- }
- }
-
- /**
- * Simply delegates to {@link #doExecuteCommand(IsisTransactionManager, Command)}.
- *
- * Overridable, so execution policy can be adjusted if required.
- *
- * @return - whether to process any further commands.
- */
- protected Boolean executeCommand(
- final IsisTransactionManager transactionManager,
- final Command command) {
- return doExecuteCommand(transactionManager, command);
- }
-
- /**
- * Not overrideable, but intended to be called by {@link #executeCommand(IsisTransactionManager, Command)} (which is).
- *
- * @return - whether to process any further commands.
- */
- protected final Boolean doExecuteCommand(
- final IsisTransactionManager transactionManager,
- final Command command) {
-
- // setup for us by IsisTransactionManager; will have the transactionId of the backgroundCommand
- final Interaction backgroundInteraction = interactionContext.getInteraction();
-
- final String memento = command.getMemento();
-
- org.apache.isis.applib.annotation.Command.ExecuteIn executeIn = command.getExecuteIn();
-
- LOG.info("Executing: {} {}", executeIn, command.getMemberIdentifier());
-
- RuntimeException exceptionIfAny = null;
- String origExceptionIfAny = null;
-
- try {
- command.setExecutor(Executor.BACKGROUND);
-
- // responsibility for setting the Command#startedAt is in the ActionInvocationFacet or
- // PropertySetterFacet, but tthis is run if the domain object was found. If the domain object is
- // thrown then we would have a command with only completedAt, which is inconsistent.
- // Therefore instead we copy down from the backgroundInteraction (similar to how we populate the
- // completedAt at the end)
- final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
-
- final Timestamp startedAt = priorExecution != null
- ? priorExecution.getStartedAt()
- : clockService.nowAsJavaSqlTimestamp();
- final Timestamp completedAt =
- priorExecution != null
- ? priorExecution.getCompletedAt()
- : clockService.nowAsJavaSqlTimestamp(); // close enough...
-
- command.setStartedAt(startedAt);
- command.setCompletedAt(completedAt);
-
- final boolean legacy = memento.startsWith("<memento");
- if(legacy) {
-
- final ActionInvocationMemento aim = new ActionInvocationMemento(mementoService, memento);
-
- final String actionId = aim.getActionId();
-
- final Bookmark targetBookmark = aim.getTarget();
- final Object targetObject = bookmarkService.lookup(
- targetBookmark, BookmarkService2.FieldResetPolicy.RESET);
-
- final ObjectAdapter targetAdapter = adapterFor(targetObject);
- final ObjectSpecification specification = targetAdapter.getSpecification();
-
- final ObjectAction objectAction = findActionElseNull(specification, actionId);
- if(objectAction == null) {
- throw new RuntimeException(String.format("Unknown action '%s'", actionId));
- }
-
- // TODO: background commands won't work for mixin actions...
- // ... we obtain the target from the bookmark service (above), which will
- // simply fail for a mixin. Instead we would need to serialize out the mixedInAdapter
- // and also capture the mixinType within the aim memento.
- final ObjectAdapter mixedInAdapter = null;
-
- final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
- final ObjectAdapter resultAdapter = objectAction.execute(
- targetAdapter, mixedInAdapter, argAdapters, InteractionInitiatedBy.FRAMEWORK);
-
- if(resultAdapter != null) {
- Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
- command.setResult(resultBookmark);
- backgroundInteraction.getCurrentExecution().setReturned(resultAdapter.getObject());
- }
-
- } else {
-
- final CommandDto dto = jaxbService.fromXml(CommandDto.class, memento);
-
- // if the command being executed was replayed, then in its userData it will holds
- // details of any exception that might have occurred.
- origExceptionIfAny = CommandDtoUtils.getUserData(dto, CommandWithDto.USERDATA_KEY_EXCEPTION);
-
- final MemberDto memberDto = dto.getMember();
- final String memberId = memberDto.getMemberIdentifier();
-
- final OidsDto oidsDto = CommandDtoUtils.targetsFor(dto);
- final List<OidDto> targetOidDtos = oidsDto.getOid();
-
- final InteractionType interactionType = memberDto.getInteractionType();
- if(interactionType == InteractionType.ACTION_INVOCATION) {
-
- final ActionDto actionDto = (ActionDto) memberDto;
-
- for (OidDto targetOidDto : targetOidDtos) {
-
- final ObjectAdapter targetAdapter = adapterFor(targetOidDto);
- final ObjectAction objectAction = findObjectAction(targetAdapter, memberId);
-
- // we pass 'null' for the mixedInAdapter; if this action _is_ a mixin then
- // it will switch the targetAdapter to be the mixedInAdapter transparently
- final ObjectAdapter[] argAdapters = argAdaptersFor(actionDto);
- final ObjectAdapter resultAdapter = objectAction.execute(
- targetAdapter, null, argAdapters, InteractionInitiatedBy.FRAMEWORK);
-
- //
- // for the result adapter, we could alternatively have used...
- // (priorExecution populated by the push/pop within the interaction object)
- //
- // final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
- // Object unused = priorExecution.getReturned();
- //
-
- // REVIEW: this doesn't really make sense if >1 action
- // in any case, the capturing of the action interaction should be the
- // responsibility of auditing/profiling
- if(resultAdapter != null) {
- Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
- command.setResult(resultBookmark);
- }
- }
- } else {
-
- final PropertyDto propertyDto = (PropertyDto) memberDto;
-
- for (OidDto targetOidDto : targetOidDtos) {
-
- final Bookmark bookmark = Bookmark.from(targetOidDto);
- final Object targetObject = bookmarkService.lookup(bookmark);
-
- final ObjectAdapter targetAdapter = adapterFor(targetObject);
-
- final OneToOneAssociation property = findOneToOneAssociation(targetAdapter, memberId);
-
- final ObjectAdapter newValueAdapter = newValueAdapterFor(propertyDto);
-
- property.set(targetAdapter, newValueAdapter, InteractionInitiatedBy.FRAMEWORK);
- // there is no return value for property modifications.
- }
- }
-
- }
-
- } catch (RuntimeException ex) {
-
- LOG.warn("Exception for: {} {}", executeIn, command.getMemberIdentifier(), ex);
-
- // hmmm, this doesn't really make sense if >1 action
- //
- // in any case, the capturing of the result of the action invocation should be the
- // responsibility of the interaction...
- command.setException(Throwables.getStackTraceAsString(ex));
-
- // lower down the stack the IsisTransactionManager will have set the transaction to abort
- // however, we don't want that to occur (because any changes made to the backgroundCommand itself
- // would also be rolled back, and it would keep getting picked up again by a scheduler for
- // processing); instead we clear the abort cause and ensure we can continue.
- transactionManager.getCurrentTransaction().clearAbortCauseAndContinue();
-
- // checked at the end
- exceptionIfAny = ex;
-
- }
-
- // it's possible that there is no priorExecution, specifically if there was an exception
- // invoking the action. We therefore need to guard that case.
- final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
- final Timestamp completedAt =
- priorExecution != null
- ? priorExecution.getCompletedAt()
- : clockService.nowAsJavaSqlTimestamp(); // close enough...
- command.setCompletedAt(completedAt);
-
- // if we hit an exception processing this command but the master did not, then quit if instructed
- return determineIfContinue(origExceptionIfAny, exceptionIfAny);
- }
-
- private static ObjectAction findObjectAction(
- final ObjectAdapter targetAdapter,
- final String actionId) throws RuntimeException {
-
- final ObjectSpecification specification = targetAdapter.getSpecification();
-
- final ObjectAction objectAction = findActionElseNull(specification, actionId);
- if(objectAction == null) {
- throw new RuntimeException(String.format("Unknown action '%s'", actionId));
- }
- return objectAction;
- }
-
- private static OneToOneAssociation findOneToOneAssociation(
- final ObjectAdapter targetAdapter,
- final String propertyId) throws RuntimeException {
-
- final ObjectSpecification specification = targetAdapter.getSpecification();
-
- final OneToOneAssociation property = findOneToOneAssociationElseNull(specification, propertyId);
- if(property == null) {
- throw new RuntimeException(String.format("Unknown property '%s'", propertyId));
- }
- return property;
- }
-
- private boolean determineIfContinue(
- final String origExceptionIfAny,
- final RuntimeException exceptionIfAny) {
-
- if(origExceptionIfAny != null) {
- return true;
- }
-
- // there was no exception on master, so do we continue?
- return determineIfContinue(exceptionIfAny);
- }
-
- private boolean determineIfContinue(final RuntimeException exceptionIfAny) {
- final boolean shouldQuit = exceptionIfAny != null &&
- onExceptionPolicy == OnExceptionPolicy.QUIT;
- return !shouldQuit;
- }
-
- private ObjectAdapter newValueAdapterFor(final PropertyDto propertyDto) {
- final ValueWithTypeDto newValue = propertyDto.getNewValue();
- final Object arg = CommonDtoUtils.getValue(newValue);
- return adapterFor(arg);
- }
-
- private static ObjectAction findActionElseNull(
- 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 static OneToOneAssociation findOneToOneAssociationElseNull(
- final ObjectSpecification specification,
- final String propertyId) {
- final List<ObjectAssociation> associations = specification.getAssociations(Contributed.INCLUDED);
- for (final ObjectAssociation association : associations) {
- if( association.getIdentifier().toClassAndNameIdentityString().equals(propertyId) &&
- association instanceof OneToOneAssociation) {
- return (OneToOneAssociation) association;
- }
- }
- return null;
- }
-
- private ObjectAdapter[] argAdaptersFor(final ActionInvocationMemento aim) {
- 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) {
- final Class<?> argType;
- try {
- argType = aim.getArgType(num);
- final Object arg = aim.getArg(num, argType);
- if(arg == null) {
- return null;
- }
- return adapterFor(arg);
-
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- private ObjectAdapter[] argAdaptersFor(final ActionDto actionDto) {
- final List<ParamDto> params = paramDtosFrom(actionDto);
- final List<ObjectAdapter> args = Lists.newArrayList(
- Iterables.transform(params, new Function<ParamDto, ObjectAdapter>() {
- @Override
- public ObjectAdapter apply(final ParamDto paramDto) {
- final Object arg = CommonDtoUtils.getValue(paramDto);
- return adapterFor(arg);
- }
- })
- );
- return args.toArray(new ObjectAdapter[]{});
- }
-
- private static List<ParamDto> paramDtosFrom(final ActionDto actionDto) {
- final ParamsDto parameters = actionDto.getParameters();
- if (parameters != null) {
- final List<ParamDto> parameterList = parameters.getParameter();
- if (parameterList != null) {
- return parameterList;
- }
- }
- return Collections.emptyList();
- }
-
- // //////////////////////////////////////
-
- @javax.inject.Inject
- BookmarkService2 bookmarkService;
-
- @javax.inject.Inject
- JaxbService jaxbService;
-
- @javax.inject.Inject
- InteractionContext interactionContext;
-
- @javax.inject.Inject
- SudoService sudoService;
-
- @javax.inject.Inject
- ClockService clockService;
}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutionAbstract.java
similarity index 59%
copy from core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
copy to core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutionAbstract.java
index 9127933..188a9e2 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutionAbstract.java
@@ -35,7 +35,6 @@ import org.apache.isis.applib.services.bookmark.BookmarkService2;
import org.apache.isis.applib.services.clock.ClockService;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.Command.Executor;
-import org.apache.isis.applib.services.command.CommandWithDto;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.iactn.InteractionContext;
import org.apache.isis.applib.services.jaxb.JaxbService;
@@ -48,9 +47,7 @@ import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
import org.apache.isis.core.runtime.system.transaction.TransactionalClosureWithReturn;
@@ -68,30 +65,10 @@ import org.apache.isis.schema.utils.CommandDtoUtils;
import org.apache.isis.schema.utils.CommonDtoUtils;
/**
- * Intended to be used as a base class for executing queued up {@link Command background action}s.
- *
- * <p>
- * This implementation uses the {@link #findBackgroundCommandsToExecute() hook method} so that it is
- * independent of the location where the actions have actually been persisted to.
*/
-public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemplate {
+public abstract class CommandExecutionAbstract extends AbstractIsisSessionTemplate {
- private final static Logger LOG = LoggerFactory.getLogger(BackgroundCommandExecution.class);
-
- public enum OnExceptionPolicy {
- /**
- * For example, regular background commands.
- */
- CONTINUE,
- /**
- * For example, replayable commands.
- *
- * To be precise, replay will quit only if there is an exception on the slave where there
- * was none on the master. Put another way, a replicated command that failed on the master
- * will not cause the slave to stop executing if it caused an exception.
- */
- QUIT,
- }
+ private final static Logger LOG = LoggerFactory.getLogger(CommandExecutionAbstract.class);
public enum SudoPolicy {
/**
@@ -104,65 +81,30 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
SWITCH,
}
- private final MementoServiceDefault mementoService;
- private final OnExceptionPolicy onExceptionPolicy;
private final SudoPolicy sudoPolicy;
- /**
- * Defaults to the historical defaults * for running background commands.
- */
- public BackgroundCommandExecution() {
- this(OnExceptionPolicy.CONTINUE, SudoPolicy.NO_SWITCH);
- }
-
- public BackgroundCommandExecution(
- final OnExceptionPolicy onExceptionPolicy,
- final SudoPolicy sudoPolicy) {
- this.onExceptionPolicy = onExceptionPolicy;
+ protected CommandExecutionAbstract(final SudoPolicy sudoPolicy) {
this.sudoPolicy = sudoPolicy;
-
- // same as configured by BackgroundServiceDefault
- mementoService = new MementoServiceDefault().withNoEncoding();
- }
-
- // //////////////////////////////////////
-
-
- protected void doExecute(Object context) {
-
- final PersistenceSession persistenceSession = getPersistenceSession();
- final IsisTransactionManager transactionManager = getTransactionManager(persistenceSession);
- final List<Command> commands = Lists.newArrayList();
- transactionManager.executeWithinTransaction(new TransactionalClosure() {
- @Override
- public void execute() {
- commands.addAll(findBackgroundCommandsToExecute());
- }
- });
-
- LOG.debug("{}: Found {} to execute", getClass().getName(), commands.size());
-
- for (final Command command : commands) {
-
- final boolean shouldContinue = execute(transactionManager, command);
- if(!shouldContinue) {
- LOG.info("NOT continuing to process any further commands, quitting execution");
- return;
- }
- }
}
- /**
- * Mandatory hook method
- */
- protected abstract List<? extends Command> findBackgroundCommandsToExecute();
-
// //////////////////////////////////////
/**
- * @return - whether to process any further commands.
+ * Executes the command within a transaction, and with respect to the specified {@link SudoPolicy}
+ * specified in the constructor.
+ *
+ * <p>
+ * Intended to be called from an override of {@link #doExecute(Object)},
+ * not from {@link #doExecuteWithTransaction(Object)} (because the error handling is different).
+ * </p>
+ *
+ * <p>
+ * Subclasses can add additional policies (eg adjusting the clock) by overriding {@link #executeCommand(IsisTransactionManager, Command)} and delegating to {@link #doExecuteCommand(IsisTransactionManager, Command)} as required.
+ * </p>
+ *
+ * @return - any exception arising. We don't throw this exception, because an exception might be what is expected (eg if replaying a command that itself failed to execute).
*/
- private boolean execute(
+ protected final Exception execute(
final IsisTransactionManager transactionManager,
final Command command) {
@@ -199,32 +141,26 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
}
});
- return determineIfContinue(ex);
+ return ex;
}
}
- /**
- * @return - whether to process any further commands.
- */
- private Boolean executeCommandWithinTran(
+ private Exception executeCommandWithinTran(
final IsisTransactionManager transactionManager,
final Command command) {
return transactionManager.executeWithinTransaction(
command,
- new TransactionalClosureWithReturn<Boolean>() {
+ new TransactionalClosureWithReturn<Exception>() {
@Override
- public Boolean execute() {
+ public Exception execute() {
return executeCommandPerSudoPolicy(transactionManager, command);
}
});
}
- /**
- * @return - whether to process any further commands.
- */
- private Boolean executeCommandPerSudoPolicy(
+ private Exception executeCommandPerSudoPolicy(
final IsisTransactionManager transactionManager,
final Command command) {
@@ -233,9 +169,9 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
return executeCommand(transactionManager, command);
case SWITCH:
final String user = command.getUser();
- return sudoService.sudo(user, new Callable<Boolean>() {
+ return sudoService.sudo(user, new Callable<Exception>() {
@Override
- public Boolean call() {
+ public Exception call() {
return executeCommand(transactionManager, command);
}
});
@@ -247,22 +183,25 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
/**
* Simply delegates to {@link #doExecuteCommand(IsisTransactionManager, Command)}.
*
- * Overridable, so execution policy can be adjusted if required.
+ * Overridable, so execution policy can be adjusted if required,
+ * eg when replaying, adjust the clock before executing the command.
*
- * @return - whether to process any further commands.
+ * @return - any exception arising
*/
- protected Boolean executeCommand(
+ protected Exception executeCommand(
final IsisTransactionManager transactionManager,
final Command command) {
return doExecuteCommand(transactionManager, command);
}
/**
- * Not overrideable, but intended to be called by {@link #executeCommand(IsisTransactionManager, Command)} (which is).
+ * Not overrideable, but intended to be called by
+ * {@link #executeCommand(IsisTransactionManager, Command)} (which is).
*
- * @return - whether to process any further commands.
+ * @return - any exception arising. We don't throw this exception, because an exception might be
+ * what is expected (eg if replaying a command that itself failed to execute).
*/
- protected final Boolean doExecuteCommand(
+ protected final Exception doExecuteCommand(
final IsisTransactionManager transactionManager,
final Command command) {
@@ -276,13 +215,12 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
LOG.info("Executing: {} {}", executeIn, command.getMemberIdentifier());
RuntimeException exceptionIfAny = null;
- String origExceptionIfAny = null;
try {
command.setExecutor(Executor.BACKGROUND);
// responsibility for setting the Command#startedAt is in the ActionInvocationFacet or
- // PropertySetterFacet, but tthis is run if the domain object was found. If the domain object is
+ // PropertySetterFacet, but this is run if the domain object was found. If the domain object is
// thrown then we would have a command with only completedAt, which is inconsistent.
// Therefore instead we copy down from the backgroundInteraction (similar to how we populate the
// completedAt at the end)
@@ -299,107 +237,64 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
command.setStartedAt(startedAt);
command.setCompletedAt(completedAt);
- final boolean legacy = memento.startsWith("<memento");
- if(legacy) {
-
- final ActionInvocationMemento aim = new ActionInvocationMemento(mementoService, memento);
-
- final String actionId = aim.getActionId();
-
- final Bookmark targetBookmark = aim.getTarget();
- final Object targetObject = bookmarkService.lookup(
- targetBookmark, BookmarkService2.FieldResetPolicy.RESET);
-
- final ObjectAdapter targetAdapter = adapterFor(targetObject);
- final ObjectSpecification specification = targetAdapter.getSpecification();
-
- final ObjectAction objectAction = findActionElseNull(specification, actionId);
- if(objectAction == null) {
- throw new RuntimeException(String.format("Unknown action '%s'", actionId));
- }
-
- // TODO: background commands won't work for mixin actions...
- // ... we obtain the target from the bookmark service (above), which will
- // simply fail for a mixin. Instead we would need to serialize out the mixedInAdapter
- // and also capture the mixinType within the aim memento.
- final ObjectAdapter mixedInAdapter = null;
-
- final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
- final ObjectAdapter resultAdapter = objectAction.execute(
- targetAdapter, mixedInAdapter, argAdapters, InteractionInitiatedBy.FRAMEWORK);
-
- if(resultAdapter != null) {
- Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
- command.setResult(resultBookmark);
- backgroundInteraction.getCurrentExecution().setReturned(resultAdapter.getObject());
- }
-
- } else {
-
- final CommandDto dto = jaxbService.fromXml(CommandDto.class, memento);
-
- // if the command being executed was replayed, then in its userData it will holds
- // details of any exception that might have occurred.
- origExceptionIfAny = CommandDtoUtils.getUserData(dto, CommandWithDto.USERDATA_KEY_EXCEPTION);
+ final CommandDto dto = jaxbService.fromXml(CommandDto.class, memento);
- final MemberDto memberDto = dto.getMember();
- final String memberId = memberDto.getMemberIdentifier();
+ final MemberDto memberDto = dto.getMember();
+ final String memberId = memberDto.getMemberIdentifier();
- final OidsDto oidsDto = CommandDtoUtils.targetsFor(dto);
- final List<OidDto> targetOidDtos = oidsDto.getOid();
+ final OidsDto oidsDto = CommandDtoUtils.targetsFor(dto);
+ final List<OidDto> targetOidDtos = oidsDto.getOid();
- final InteractionType interactionType = memberDto.getInteractionType();
- if(interactionType == InteractionType.ACTION_INVOCATION) {
+ final InteractionType interactionType = memberDto.getInteractionType();
+ if(interactionType == InteractionType.ACTION_INVOCATION) {
- final ActionDto actionDto = (ActionDto) memberDto;
+ final ActionDto actionDto = (ActionDto) memberDto;
- for (OidDto targetOidDto : targetOidDtos) {
+ for (OidDto targetOidDto : targetOidDtos) {
- final ObjectAdapter targetAdapter = adapterFor(targetOidDto);
- final ObjectAction objectAction = findObjectAction(targetAdapter, memberId);
+ final ObjectAdapter targetAdapter = adapterFor(targetOidDto);
+ final ObjectAction objectAction = findObjectAction(targetAdapter, memberId);
- // we pass 'null' for the mixedInAdapter; if this action _is_ a mixin then
- // it will switch the targetAdapter to be the mixedInAdapter transparently
- final ObjectAdapter[] argAdapters = argAdaptersFor(actionDto);
- final ObjectAdapter resultAdapter = objectAction.execute(
- targetAdapter, null, argAdapters, InteractionInitiatedBy.FRAMEWORK);
+ // we pass 'null' for the mixedInAdapter; if this action _is_ a mixin then
+ // it will switch the targetAdapter to be the mixedInAdapter transparently
+ final ObjectAdapter[] argAdapters = argAdaptersFor(actionDto);
+ final ObjectAdapter resultAdapter = objectAction.execute(
+ targetAdapter, null, argAdapters, InteractionInitiatedBy.FRAMEWORK);
- //
- // for the result adapter, we could alternatively have used...
- // (priorExecution populated by the push/pop within the interaction object)
- //
- // final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
- // Object unused = priorExecution.getReturned();
- //
+ //
+ // for the result adapter, we could alternatively have used...
+ // (priorExecution populated by the push/pop within the interaction object)
+ //
+ // final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
+ // Object unused = priorExecution.getReturned();
+ //
- // REVIEW: this doesn't really make sense if >1 action
- // in any case, the capturing of the action interaction should be the
- // responsibility of auditing/profiling
- if(resultAdapter != null) {
- Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
- command.setResult(resultBookmark);
- }
+ // REVIEW: this doesn't really make sense if >1 action
+ // in any case, the capturing of the action interaction should be the
+ // responsibility of auditing/profiling
+ if(resultAdapter != null) {
+ Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
+ command.setResult(resultBookmark);
}
- } else {
+ }
+ } else {
- final PropertyDto propertyDto = (PropertyDto) memberDto;
+ final PropertyDto propertyDto = (PropertyDto) memberDto;
- for (OidDto targetOidDto : targetOidDtos) {
+ for (OidDto targetOidDto : targetOidDtos) {
- final Bookmark bookmark = Bookmark.from(targetOidDto);
- final Object targetObject = bookmarkService.lookup(bookmark);
+ final Bookmark bookmark = Bookmark.from(targetOidDto);
+ final Object targetObject = bookmarkService.lookup(bookmark);
- final ObjectAdapter targetAdapter = adapterFor(targetObject);
+ final ObjectAdapter targetAdapter = adapterFor(targetObject);
- final OneToOneAssociation property = findOneToOneAssociation(targetAdapter, memberId);
+ final OneToOneAssociation property = findOneToOneAssociation(targetAdapter, memberId);
- final ObjectAdapter newValueAdapter = newValueAdapterFor(propertyDto);
+ final ObjectAdapter newValueAdapter = newValueAdapterFor(propertyDto);
- property.set(targetAdapter, newValueAdapter, InteractionInitiatedBy.FRAMEWORK);
- // there is no return value for property modifications.
- }
+ property.set(targetAdapter, newValueAdapter, InteractionInitiatedBy.FRAMEWORK);
+ // there is no return value for property modifications.
}
-
}
} catch (RuntimeException ex) {
@@ -432,8 +327,7 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
: clockService.nowAsJavaSqlTimestamp(); // close enough...
command.setCompletedAt(completedAt);
- // if we hit an exception processing this command but the master did not, then quit if instructed
- return determineIfContinue(origExceptionIfAny, exceptionIfAny);
+ return exceptionIfAny;
}
private static ObjectAction findObjectAction(
@@ -462,24 +356,6 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
return property;
}
- private boolean determineIfContinue(
- final String origExceptionIfAny,
- final RuntimeException exceptionIfAny) {
-
- if(origExceptionIfAny != null) {
- return true;
- }
-
- // there was no exception on master, so do we continue?
- return determineIfContinue(exceptionIfAny);
- }
-
- private boolean determineIfContinue(final RuntimeException exceptionIfAny) {
- final boolean shouldQuit = exceptionIfAny != null &&
- onExceptionPolicy == OnExceptionPolicy.QUIT;
- return !shouldQuit;
- }
-
private ObjectAdapter newValueAdapterFor(final PropertyDto propertyDto) {
final ValueWithTypeDto newValue = propertyDto.getNewValue();
final Object arg = CommonDtoUtils.getValue(newValue);
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
index a554d7c..ac40524 100644
--- 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
@@ -90,7 +90,7 @@ public abstract class AbstractIsisSessionTemplate {
// //////////////////////////////////////
- protected ObjectAdapter adapterFor(final Object targetObject) {
+ protected final ObjectAdapter adapterFor(final Object targetObject) {
if(targetObject instanceof OidDto) {
final OidDto oidDto = (OidDto) targetObject;
return adapterFor(oidDto);
@@ -117,17 +117,17 @@ public abstract class AbstractIsisSessionTemplate {
return getPersistenceSession().adapterFor(targetObject);
}
- protected ObjectAdapter adapterFor(final OidDto oidDto) {
+ protected final ObjectAdapter adapterFor(final OidDto oidDto) {
final Bookmark bookmark = Bookmark.from(oidDto);
return adapterFor(bookmark);
}
- protected ObjectAdapter adapterFor(final Bookmark bookmark) {
+ protected final ObjectAdapter adapterFor(final Bookmark bookmark) {
final RootOid rootOid = RootOid.create(bookmark);
return adapterFor(rootOid);
}
- protected ObjectAdapter adapterFor(final RootOid rootOid) {
+ protected final ObjectAdapter adapterFor(final RootOid rootOid) {
return getPersistenceSession().adapterFor(rootOid);
}
--
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.