You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2023/08/25 12:26:38 UTC
[causeway] branch CAUSEWAY-3557 updated (25bab1508e -> 5596561fb3)
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a change to branch CAUSEWAY-3557
in repository https://gitbox.apache.org/repos/asf/causeway.git
discard 25bab1508e CAUSEWAY-3557: simplifies FakeScheduler
discard 146677998d CAUSEWAY-3557: just improves javadoc for Can, emphasise it can only hold non-null values.
discard bf5ee961b7 CAUSEWAY-3557: adds in FakeScheduler
add cc56f1a9a8 CAUSEWAY-3555: fix prev. commit: handle the null args case well
add e082943b58 CAUSEWAY-2297: removes ambiguous _Lists.of(...)
new 8f263617b1 CAUSEWAY-3557: adds in FakeScheduler
new ba1ad0a5cb CAUSEWAY-3557: just improves javadoc for Can, emphasise it can only hold non-null values.
new 5596561fb3 CAUSEWAY-3557: simplifies FakeScheduler
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (25bab1508e)
\
N -- N -- N refs/heads/CAUSEWAY-3557 (5596561fb3)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../applib/id/LogicalTypeTest_valueSemantics.java | 5 +-
.../ObjectContractsTest_equals_and_hashCode.java | 5 +-
.../commons/internal/collections/_Lists.java | 138 ++++++++++++++++-----
.../commons/collections/CanCompareTest.java | 2 +-
.../commons/internal/base/ReductionTest.java | 8 +-
.../commons/internal/collections/_ArraysTest.java | 102 +++++++--------
.../collections/_ListsTest.java} | 47 ++++---
.../commons/internal/collections/_SetsTest.java | 73 +++++------
.../core/config/messages/MessageRegistry.java | 4 +-
.../core/config/util/ValueMaskingUtil.java | 3 +-
.../contract/ComparableContractTester.java | 10 +-
.../_testing/MetaModelContext_forTesting.java | 3 +-
.../core/metamodel/commons/ClassExtensions.java | 4 +-
.../metamodel/commons/ListUtilsTest_insert.java | 8 +-
.../metamodel/facets/CollectionFacetUtilsTest.java | 3 +-
.../ordering/memberorder/DeweyOrderSetTest.java | 7 +-
...jectAssociationPredicatesTest_visibleWhere.java | 3 +-
.../ClassSubstitutorTest_getClass.java | 5 +-
.../wrapper/WrapperFactoryDefault.java | 4 +-
.../email/EmailServiceDefaultTest_actually.java | 8 +-
.../AuthenticationRequestLogonFixture.java | 4 +-
.../testdomain/interact/ActionInteractionTest.java | 4 +-
.../value/ActionInteractionProbeImpl.java | 4 -
.../testdomain/value/ValueSemanticsTest.java | 15 ++-
.../testdomain/value/ValueSemanticsTester.java | 120 +++++++++++-------
...ionHasParamSupportingMethodTypeOfReference.java | 3 +-
...ActionHasParamSupportingMethodTypeOfString.java | 3 +-
.../model/good/ProperChoicesWhenChoicesFrom.java | 3 +-
.../InteractionDemo_biListOfString.java | 19 ++-
.../interaction/InteractionDemo_negotiate.java | 46 +++----
.../model/valuetypes/ValueTypeExample.java | 106 +++++++++-------
.../causeway/testdomain/rospec/RoSpecSampler.java | 13 +-
.../dom/comparable/ComparableContractTester.java | 10 +-
.../causeway/tooling/model4adoc/NodeWriter.java | 3 +-
.../CausewayRestfulObjectsInteractionFilter.java | 3 +-
35 files changed, 451 insertions(+), 347 deletions(-)
copy commons/src/test/java/org/apache/causeway/commons/{functional/ThrowingRunnableTest.java => internal/collections/_ListsTest.java} (53%)
[causeway] 01/03: CAUSEWAY-3557: adds in FakeScheduler
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-3557
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 8f263617b19142fa55b4bbfed8325cda161b16b7
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Aug 25 11:45:48 2023 +0100
CAUSEWAY-3557: adds in FakeScheduler
---
.../commandlog/applib/dom/BackgroundService.java | 1 +
.../applib/fakescheduler/FakeScheduler.java | 121 +++++++++++++++++++++
2 files changed, 122 insertions(+)
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
index 2496f2a9b7..c9bcfefed7 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
@@ -55,6 +55,7 @@ import lombok.val;
* </p>
*
* @see WrapperFactory
+ * @see org.apache.causeway.extensions.commandlog.applib.fakescheduler.FakeScheduler
* @since 2.0 {@index}
*/
@Service
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java
new file mode 100644
index 0000000000..0724f6a80c
--- /dev/null
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java
@@ -0,0 +1,121 @@
+package org.apache.causeway.extensions.commandlog.applib.fakescheduler;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+
+import org.apache.causeway.applib.services.clock.ClockService;
+import org.apache.causeway.applib.services.command.Command;
+import org.apache.causeway.applib.services.command.CommandExecutorService;
+import org.apache.causeway.applib.services.iactnlayer.InteractionService;
+import org.apache.causeway.applib.services.xactn.TransactionService;
+import org.apache.causeway.extensions.commandlog.applib.dom.CommandLogEntry;
+import org.apache.causeway.extensions.commandlog.applib.dom.CommandLogEntryRepository;
+import org.apache.causeway.schema.cmd.v2.CommandDto;
+
+import lombok.val;
+
+/**
+ * Intended to support integration testing which uses the
+ * {@link org.apache.causeway.extensions.commandlog.applib.dom.BackgroundService} to create background
+ * {@link CommandLogEntry command}s, that the integration test then needs to be executed.
+ *
+ * @see org.apache.causeway.extensions.commandlog.applib.dom.BackgroundService
+ * @since 2.0 {@index}
+ */
+@Service
+public class FakeScheduler {
+
+ public enum NoCommandsPolicy {
+ /**
+ * If no commands are found, simply return
+ */
+ RELAXED,
+ /**
+ * If no commands are found, then throw an exception. The idea here is that this is a utility to support integration testing; in some tests we might want to fail if no background commands were found.
+ */
+ STRICT;
+ }
+
+ /**
+ *
+ * @param waitForMillis how long to wait for the background commands to execute. The commands themselves run in a background thread to this.
+ * @param noCommandsPolicy what to do if there are no commands found to be executed.
+ * @return the number of commands still to be processed. This will generally be 0, but could be non-zero if not enough time was provided to wait.
+ * @throws InterruptedException
+ */
+ public int runBackgroundCommands(
+ final Integer waitForMillis,
+ final NoCommandsPolicy noCommandsPolicy) throws InterruptedException {
+
+ // we obtain the list of Commands first; we use their CommandDto as it is serializable across transactions
+ List<CommandDto> commandDtos = commandLogEntryRepository.findBackgroundAndNotYetStarted()
+ .stream()
+ .map(CommandLogEntry::getCommandDto)
+ .collect(Collectors.toList());
+
+ if(commandDtos.isEmpty()) {
+ switch (noCommandsPolicy) {
+ case STRICT:
+ throw new IllegalStateException("There are no background commands to be started");
+ case RELAXED:
+ default:
+ return 0;
+ }
+ }
+
+ long startAt = nowInMillis();
+
+ transactionService.flushTransaction();
+
+ Thread thread = new Thread(() -> execute(commandDtos));
+ thread.start();
+
+ boolean hitTimeout = false;
+ List<CommandLogEntry> commandsToProcess;
+ while(!(commandsToProcess = commandLogEntryRepository.findBackgroundAndNotYetStarted()).isEmpty() && !hitTimeout) {
+ Thread.sleep(100L);
+ hitTimeout = nowInMillis() > startAt + waitForMillis;
+ }
+
+ return commandsToProcess.size();
+ }
+
+ private long nowInMillis() {
+ return clockService.getClock().nowAsEpochMilli();
+ }
+
+ private void execute(List<CommandDto> commandDtos) {
+
+ for (val commandDto : commandDtos) {
+ interactionService.runAnonymous(() -> {
+ transactionService.runTransactional(Propagation.REQUIRED, () -> {
+ // look up the CommandLogEntry again because we are within a new transaction.
+ val commandLogEntryIfAny = commandLogEntryRepository.findByInteractionId(UUID.fromString(commandDto.getInteractionId()));
+
+ // TODO: this is a hack, really should be in CommandExecutorService
+ val command = interactionService.currentInteraction().map(x -> x.getCommand()).orElseThrow(() -> new IllegalStateException("Cannot obtain current interaction/command"));
+ command.updater().setPublishingPhase(Command.CommandPublishingPhase.READY);
+
+ commandLogEntryIfAny.ifPresent(commandLogEntry ->
+ commandExecutorService.executeCommand(
+ CommandExecutorService.InteractionContextPolicy.NO_SWITCH, commandDto));
+ })
+ .ifFailureFail();
+ }
+ );
+ }
+ }
+
+ @Inject CommandLogEntryRepository<CommandLogEntry> commandLogEntryRepository;
+ @Inject CommandExecutorService commandExecutorService;
+ @Inject TransactionService transactionService;
+ @Inject InteractionService interactionService;
+ @Inject ClockService clockService;
+
+}
[causeway] 03/03: CAUSEWAY-3557: simplifies FakeScheduler
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-3557
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 5596561fb35992b6d5ba44ff3c3cf258d7a60710
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Aug 25 13:18:09 2023 +0100
CAUSEWAY-3557: simplifies FakeScheduler
is ok to remove a workaround that it had in it
---
.../core/interaction/session/CausewayInteraction.java | 13 ++-----------
.../command/CommandExecutorServiceDefault.java | 5 +++--
.../commandlog/applib/fakescheduler/FakeScheduler.java | 4 ----
3 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java b/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
index c8fc97a9f0..a3cb817071 100644
--- a/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
+++ b/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
@@ -103,7 +103,8 @@ implements InteractionInternal {
final CommandPublisher commandPublisher,
final Command command) {
- pushAndStart(actionInvocation, clockService, metricsService, commandPublisher, command);
+ push(actionInvocation);
+ start(actionInvocation, clockService, metricsService, commandPublisher, command);
try {
return executeInternal(memberExecutor, actionInvocation);
} finally {
@@ -111,16 +112,6 @@ implements InteractionInternal {
}
}
- private void pushAndStart(
- final ActionInvocation actionInvocation,
- final ClockService clockService,
- final MetricsService metricsService,
- final CommandPublisher commandPublisher,
- final Command command) {
- push(actionInvocation);
- start(actionInvocation, clockService, metricsService, commandPublisher, command);
- }
-
@Override
public Object execute(
final MemberExecutor<PropertyEdit> memberExecutor,
diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java
index eda62c2d21..fd3fa9e7d9 100644
--- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java
@@ -28,8 +28,6 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
-import org.apache.causeway.commons.functional.Try;
-import org.apache.causeway.core.metamodel.services.publishing.CommandPublisher;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@@ -45,11 +43,13 @@ import org.apache.causeway.applib.services.xactn.TransactionService;
import org.apache.causeway.applib.util.schema.CommandDtoUtils;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.functional.IndexedFunction;
+import org.apache.causeway.commons.functional.Try;
import org.apache.causeway.commons.internal.base._NullSafe;
import org.apache.causeway.commons.internal.exceptions._Exceptions;
import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.core.metamodel.services.publishing.CommandPublisher;
import org.apache.causeway.core.metamodel.services.schema.SchemaValueMarshaller;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
@@ -63,6 +63,7 @@ import org.apache.causeway.schema.cmd.v2.ParamDto;
import org.apache.causeway.schema.cmd.v2.ParamsDto;
import org.apache.causeway.schema.cmd.v2.PropertyDto;
import org.apache.causeway.schema.common.v2.InteractionType;
+
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.val;
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java
index 0724f6a80c..5cfe02c8c2 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/fakescheduler/FakeScheduler.java
@@ -98,10 +98,6 @@ public class FakeScheduler {
// look up the CommandLogEntry again because we are within a new transaction.
val commandLogEntryIfAny = commandLogEntryRepository.findByInteractionId(UUID.fromString(commandDto.getInteractionId()));
- // TODO: this is a hack, really should be in CommandExecutorService
- val command = interactionService.currentInteraction().map(x -> x.getCommand()).orElseThrow(() -> new IllegalStateException("Cannot obtain current interaction/command"));
- command.updater().setPublishingPhase(Command.CommandPublishingPhase.READY);
-
commandLogEntryIfAny.ifPresent(commandLogEntry ->
commandExecutorService.executeCommand(
CommandExecutorService.InteractionContextPolicy.NO_SWITCH, commandDto));
[causeway] 02/03: CAUSEWAY-3557: just improves javadoc for Can, emphasise it can only hold non-null values.
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-3557
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit ba1ad0a5cb135e8d3e92a763e4d879851bb841d9
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Aug 25 11:46:13 2023 +0100
CAUSEWAY-3557: just improves javadoc for Can, emphasise it can only hold non-null values.
---
.../apache/causeway/commons/collections/Can.java | 74 +++++++++++++++++-----
1 file changed, 59 insertions(+), 15 deletions(-)
diff --git a/commons/src/main/java/org/apache/causeway/commons/collections/Can.java b/commons/src/main/java/org/apache/causeway/commons/collections/Can.java
index 7e7a21fc82..8859efc19d 100644
--- a/commons/src/main/java/org/apache/causeway/commons/collections/Can.java
+++ b/commons/src/main/java/org/apache/causeway/commons/collections/Can.java
@@ -59,8 +59,10 @@ import lombok.val;
* <p>
* Same idiomatic convention applies: References to {@link Can}
* should never be initialized to {@code null}.
+ *
* <p>
- * A {@link Can} must not contain elements equal to {@code null}.
+ * <b>IMPORTANT:</b>A {@link Can} must not contain elements equal to {@code null}. If you want to store a null within
+ * a {@link Can}, then replace it with {@link Can#NULL_VALUE} placeholder first.
*
* @param <T>
* @since 2.0 {@index}
@@ -68,6 +70,12 @@ import lombok.val;
public interface Can<T>
extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
+ /**
+ * Provided for use as a placeholder for <code>null</code> values; the {@link Can} itself just treats this as
+ * just another object.
+ */
+ Object NULL_VALUE = new Object();
+
/**
* Will only ever return an empty Optional, if the elementIndex is out of bounds.
* @param elementIndex
@@ -164,6 +172,10 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Var-arg version of {@link Can#ofArray(Object[])}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
* @param <T>
* @param array
* @return non-null
@@ -176,29 +188,48 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Returns either a {@code Can} with all the elements from given {@code array}
- * or an empty {@code Can} if the {@code array} is {@code null}. Any elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * or an empty {@code Can} if the {@code array} is {@code null}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
+ * </p>
* @param <T>
* @param array
* @return non-null
*/
public static <T> Can<T> ofArray(final @Nullable T[] array) {
+ return ofArray(array, Function.identity());
+ }
+ /**
+ *
+ * @param array
+ * @param nullMapper -
+ * @return
+ * @param <T>
+ */
+ public static <T> Can<T> ofArray(T[] array, Function<T, T> nullMapper) {
if(_NullSafe.size(array)==0) {
return empty();
}
val nonNullElements = Stream.of(array)
.filter(_NullSafe::isPresent)
+ .map(nullMapper)
.collect(_CanFactory.toListWithSizeUpperBound(array.length));
return _CanFactory.ofNonNullElements(nonNullElements);
}
+
/**
* Returns either a {@code Can} with all the elements from given {@code collection}
- * or an empty {@code Can} if the {@code collection} is {@code null}. Any elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * or an empty {@code Can} if the {@code collection} is {@code null}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
* @param <T>
* @param collection
* @return non-null
@@ -220,8 +251,11 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Returns either a {@code Can} with all the elements from given {@code iterable}
- * or an empty {@code Can} if the {@code iterable} is {@code null}. Any elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * or an empty {@code Can} if the {@code iterable} is {@code null}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
* @param <T>
* @param iterable
* @return non-null
@@ -244,10 +278,14 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Returns either a {@code Can} with all the elements from given {@code enumeration}
- * or an empty {@code Can} if the {@code enumeration} is {@code null}. Any elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * or an empty {@code Can} if the {@code enumeration} is {@code null}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
* <p>
- * As side-effect, consumes given {@code enumeration}.
+ * <b>NOTE:</b> As side-effect, consumes given {@code enumeration}.
+ *
* @param <T>
* @param enumeration
* @return non-null
@@ -270,10 +308,14 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Returns either a {@code Can} with all the elements from given {@code stream}
- * or an empty {@code Can} if the {@code stream} is {@code null}. Any elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * or an empty {@code Can} if the {@code stream} is {@code null}.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ *
* <p>
- * As side-effect, consumes given {@code stream}.
+ * <b>NOTE:</b> As side-effect, consumes given {@code stream}.
+ *
* @param <T>
* @param stream
* @return non-null
@@ -356,8 +398,10 @@ extends ImmutableCollection<T>, Comparable<Can<T>>, Serializable {
/**
* Returns a {@code Can} with all the elements from this {@code Can}
- * 'transformed' by the given {@code mapper} function. Any resulting elements
- * equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
+ * 'transformed' by the given {@code mapper} function.
+ *
+ * <p>
+ * <b>NOTE:</b> Any elements equal to {@code null} are ignored and will not be contained in the resulting {@code Can}.
*
* @param <R>
* @param mapper - if absent throws if this {@code Can} is non-empty