This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/main by this push:
new 8c9669e5981 CAUSEWAY-3896: AsyncProxy API and Javadoc polishing
8c9669e5981 is described below
commit 8c9669e5981a90a9588d9e587255de820535e7db
Author: Andi Huber <[email protected]>
AuthorDate: Sat Jun 28 07:39:45 2025 +0200
CAUSEWAY-3896: AsyncProxy API and Javadoc polishing
---
.../applib/services/wrapper/WrapperFactory.java | 115 ++++++++++++---------
.../causeway/commons/functional/TryFuture.java | 58 +++++++++++
.../wrapper/AsyncProxyInternal.java | 31 ++----
.../wrapper/WrapperFactoryDefault.java | 13 ---
.../BackgroundService_IntegTestAbstract.java | 24 ++---
.../jdo/publishing/PublishingTestFactoryJdo.java | 9 +-
.../jpa/publishing/PublishingTestFactoryJpa.java | 14 +--
.../integtests/WrapperFactory_async_IntegTest.java | 12 +--
.../testdomain/interact/CommandArgumentTest.java | 6 +-
.../WrapperInteraction_Caching_IntegTest.java | 9 +-
10 files changed, 167 insertions(+), 124 deletions(-)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/WrapperFactory.java
b/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/WrapperFactory.java
index 1237f360695..21924f3e541 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/WrapperFactory.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/WrapperFactory.java
@@ -20,17 +20,19 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
import org.springframework.util.function.ThrowingConsumer;
import org.springframework.util.function.ThrowingFunction;
import org.apache.causeway.applib.exceptions.recoverable.InteractionException;
import org.apache.causeway.applib.services.factory.FactoryService;
+import org.apache.causeway.applib.services.iactnlayer.InteractionContext;
+import org.apache.causeway.applib.services.repository.RepositoryService;
import org.apache.causeway.applib.services.wrapper.control.AsyncControl;
import org.apache.causeway.applib.services.wrapper.control.SyncControl;
import org.apache.causeway.applib.services.wrapper.events.InteractionEvent;
import
org.apache.causeway.applib.services.wrapper.listeners.InteractionListener;
+import org.apache.causeway.commons.functional.TryFuture;
/**
* Provides the ability to 'wrap' a domain object such that it can
@@ -75,18 +77,30 @@
public interface WrapperFactory {
/**
+ * The result of an async proxy instantiation,
+ * that allows to submit an async invocation on the wrapped domain object.
+ *
+ * <p>The framework takes care, that an async invocation is scoped within
both an interaction-context and a transaction.
+ * Further more, {@link TryFuture}'s success values are unwrapped and
detached.
+ *
+ * <p>Terminology:
+ * <ul>
+ * <li>interaction-context: who/how/when {@link InteractionContext}</li>
+ * <li>unwrapped: plain object, not proxied {@link
WrapperFactory#unwrap}</li>
+ * <li>detached: object not attached to a persistence session
(applicable to entities only)
+ * {@link RepositoryService#detach(Object)}</li>
+ * </ul>
+ *
* @since 3.4 {@index}
- * @see CompletableFuture
+ * @see TryFuture
*/
interface AsyncProxy<T> {
- AsyncProxy<Void> thenAcceptAsync(ThrowingConsumer<? super T> action);
- <U> AsyncProxy<U> thenApplyAsync(ThrowingFunction<? super T, ? extends
U> fn);
- AsyncProxy<T> orTimeout(long timeout, TimeUnit unit);
- T join();
+ TryFuture<Void> acceptAsync(ThrowingConsumer<? super T> action);
+ <U> TryFuture<U> applyAsync(ThrowingFunction<? super T, ? extends U>
fn);
}
/**
- * Provides the "wrapper" of a domain object against which to
invoke the action.
+ * Provides the'wrapper' of a domain object against which to invoke the
action.
*
* <p>The provided {@link SyncControl} determines whether business rules
are checked first, and conversely
* whether the action is executed. There are therefore three typical
cases:
@@ -100,48 +114,49 @@ interface AsyncProxy<T> {
*
* <p>Otherwise, will do all the validations (raise exceptions as required
* etc.), but doesn't modify the model.
+ *
+ * <p>Any exceptions will be propagated, not swallowed.
*/
- <T> T wrap(T domainObject,
- SyncControl syncControl);
+ <T> T wrap(T domainObject, SyncControl syncControl);
/**
- * A convenience overload for {@link #wrap(Object, SyncControl)},
- * returning a wrapper to invoke the action synchronously, enforcing
business rules.
- * Any exceptions will be propagated, not swallowed.
+ * A convenience overload for {@link #wrap(Object, SyncControl)} with
{@code SyncControl.defaults()}.
+ * @see #wrap(Object, SyncControl)
*/
- <T> T wrap(T domainObject);
+ default <T> T wrap(T domainObject) {
+ return wrap(domainObject, SyncControl.defaults());
+ }
/**
* Provides the wrapper for a {@link FactoryService#mixin(Class, Object)
mixin}, against which to invoke the action.
*
- * <p>
- * The provided {@link SyncControl} determines whether business rules
are checked first, and conversely
- * whether the action is executed. See {@link #wrap(Object,
SyncControl)} for more details on this.
- * </p>
+ * <p>The provided {@link SyncControl} determines whether business rules
are checked first, and conversely
+ * whether the action is executed.
+ *
+ * <p>Any exceptions will be propagated, not swallowed.
+ * @see #wrap(Object, SyncControl)
*/
- <T> T wrapMixin(Class<T> mixinClass, Object mixee,
- SyncControl syncControl);
+ <T> T wrapMixin(Class<T> mixinClass, Object mixee, SyncControl
syncControl);
+
+ /**
+ * A convenience overload for {@link #wrapMixin(Class, Object,
SyncControl)} with {@code SyncControl.defaults()}.
+ * @see #wrapMixin(Class, Object, SyncControl)
+ */
+ default <T> T wrapMixin(Class<T> mixinClass, Object mixee) {
+ return wrapMixin(mixinClass, mixee, SyncControl.defaults());
+ }
/**
* Provides the wrapper for a {@link Mixin typesafe} {@link
FactoryService#mixin(Class, Object) mixin}, against which to invoke the action.
*
- * <p>
- * The provided {@link SyncControl} determines whether business rules
are checked first, and conversely
+ * <p>The provided {@link SyncControl} determines whether business rules
are checked first, and conversely
* whether the action is executed. See {@link #wrap(Object,
SyncControl)} for more details on this.
- * </p>
*/
default <T extends Mixin<MIXEE>, MIXEE> T wrapMixinT(Class<T> mixinClass,
MIXEE mixee,
SyncControl syncControl) {
return wrapMixin(mixinClass, mixee, syncControl);
}
- /**
- * A convenience overload for {@link #wrapMixin(Class, Object,
SyncControl)},
- * returning a wrapper to invoke the action synchronously, enforcing
business rules.
- * Any exceptions will be propagated, not swallowed.
- */
- <T> T wrapMixin(Class<T> mixinClass, Object mixee);
-
/**
* A convenience overload for {@link #wrapMixinT(Class, Object,
SyncControl)},
* returning a wrapper to invoke the action synchronously, enforcing
business rules.
@@ -154,8 +169,7 @@ default <T extends Mixin<MIXEE>, MIXEE> T
wrapMixinT(Class<T> mixinClass, MIXEE
/**
* Obtains the underlying domain object, if wrapped.
*
- * <p>
- * If the object {@link #isWrapper(Object) is not wrapped}, then
+ * <p>If the object {@link #isWrapper(Object) is not wrapped}, then
* should just return the object back unchanged.
*/
<T> T unwrap(T possibleWrappedDomainObject);
@@ -163,47 +177,54 @@ default <T extends Mixin<MIXEE>, MIXEE> T
wrapMixinT(Class<T> mixinClass, MIXEE
/**
* Whether the supplied object is a wrapper around a domain object.
*
- * @param <T>
* @param possibleWrappedDomainObject
* - object that might or might not be a wrapper.
*/
<T> boolean isWrapper(T possibleWrappedDomainObject);
- //
// -- ASYNC WRAPPING
- //
/**
* Returns a {@link CompletableFuture} holding a proxy object for the
provided {@code domainObject},
* through which one can execute the action asynchronously (in another
thread).
*
* @param <T> - the type of the domain object
- * @param domainObject
- * @param asyncControl
*
* @since 3.4
*/
<T> AsyncProxy<T> asyncWrap(T domainObject, AsyncControl asyncControl);
/**
- * Returns a {@link CompletableFuture} holding a proxy object for the
provided {@code mixinClass},
+ * A convenience overload for {@link #asyncWrap(Object, AsyncControl)}
with {@code AsyncControl.defaults()}.
+ * @see #asyncWrap(Object, AsyncControl)
+ *
+ * @since 3.4
+ */
+ default <T> AsyncProxy<T> asyncWrap(T domainObject) {
+ return asyncWrap(domainObject, AsyncControl.defaults());
+ }
+
+ /**
+ * Returns a {@link AsyncProxy} holding a proxy object for the provided
{@code mixinClass},
* through which one can execute the action asynchronously (in another
thread).
*
* @param <T> - the type of the mixin
- * @param mixinClass
- * @param mixee
- * @param asyncControl
*
* @since 3.4
*/
- <T> AsyncProxy<T> asyncWrapMixin(
- Class<T> mixinClass,
- Object mixee,
- AsyncControl asyncControl);
+ <T> AsyncProxy<T> asyncWrapMixin(Class<T> mixinClass, Object mixee,
AsyncControl asyncControl);
+
+ /**
+ * A convenience overload for {@link #asyncWrapMixin(Class, Object,
AsyncControl)} with {@code AsyncControl.defaults()}.
+ * @see #asyncWrapMixin(Class, Object, AsyncControl)
+ *
+ * @since 3.4
+ */
+ default <T> AsyncProxy<T> asyncWrapMixin(Class<T> mixinClass, Object
mixee) {
+ return asyncWrapMixin(mixinClass, mixee, AsyncControl.defaults());
+ }
- //
// -- INTERACTION EVENT HANDLING
- //
/**
* All {@link InteractionListener}s that have been registered using
@@ -239,4 +260,6 @@ boolean removeInteractionListener(
InteractionListener listener);
void notifyListeners(InteractionEvent ev);
+
+
}
diff --git
a/commons/src/main/java/org/apache/causeway/commons/functional/TryFuture.java
b/commons/src/main/java/org/apache/causeway/commons/functional/TryFuture.java
new file mode 100644
index 00000000000..9635d33b2e7
--- /dev/null
+++
b/commons/src/main/java/org/apache/causeway/commons/functional/TryFuture.java
@@ -0,0 +1,58 @@
+/*
+ * 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.causeway.commons.functional;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import lombok.NonNull;
+
+/**
+ * Wraps a {@link Future} and catches any exceptions within a {@link Try},
+ * such that no exceptions escape the future's {@code get(..)} methods.
+ *
+ * @param <T> The result type returned by this TryFuture's {@code tryGet(..)}
methods
+ * @see Future
+ * @see Try
+ * @since 3.4
+ */
+public record TryFuture<T>(@NonNull Future<T> future) {
+
+ /**
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task or executor is null
+ */
+ public TryFuture(@NonNull Callable<T> task, @NonNull ExecutorService
executor) {
+ this(executor.submit(task));
+ }
+
+ public Try<T> tryGet() {
+ return Try.call(future::get);
+ }
+
+ public Try<T> tryGet(long timeout, TimeUnit unit) {
+ return Try.call(()->future.get(timeout, unit));
+ }
+
+}
+
diff --git
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/AsyncProxyInternal.java
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/AsyncProxyInternal.java
index e475eb4dccb..84c5439c0fb 100644
---
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/AsyncProxyInternal.java
+++
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/AsyncProxyInternal.java
@@ -18,37 +18,28 @@
*/
package org.apache.causeway.core.runtimeservices.wrapper;
-import java.util.concurrent.Callable;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import org.springframework.util.function.ThrowingConsumer;
import org.springframework.util.function.ThrowingFunction;
import org.apache.causeway.applib.services.wrapper.WrapperFactory.AsyncProxy;
+import org.apache.causeway.commons.functional.TryFuture;
-import lombok.SneakyThrows;
-
-//TODO this is just a proof of concept; chaining makes non sense once future
no longer holds a proxy
record AsyncProxyInternal<T>(
Future<T> future,
AsyncExecutor executor) implements AsyncProxy<T> {
- @Override public AsyncProxy<Void> thenAcceptAsync(ThrowingConsumer<? super
T> action) {
- return thenApplyAsync(adapt(action));
- }
-
- @Override public <U> AsyncProxy<U> thenApplyAsync(ThrowingFunction<? super
T, ? extends U> fn) {
- return map(()->fn.apply(future.get()));
+ @Override
+ public TryFuture<Void> acceptAsync(
+ ThrowingConsumer<? super T> action) {
+ return applyAsync(adapt(action));
}
- @Override public AsyncProxy<T> orTimeout(long timeout, TimeUnit unit) {
- return map(()->future.get(timeout, unit));
- }
-
- @SneakyThrows
- @Override public T join() {
- return future.get();
+ @Override
+ public <U> TryFuture<U> applyAsync(
+ ThrowingFunction<? super T, ? extends U> fn) {
+ return new TryFuture<>(()->fn.apply(future.get()), executor);
}
// -- HELPER
@@ -58,8 +49,4 @@ private ThrowingFunction<? super T, Void>
adapt(ThrowingConsumer<? super T> acti
return t->{action.accept(t); return (Void)null; };
}
- private <U> AsyncProxy<U> map(Callable<U> callable) {
- return new AsyncProxyInternal<>(executor.submit(callable), executor);
- }
-
}
\ No newline at end of file
diff --git
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/WrapperFactoryDefault.java
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/WrapperFactoryDefault.java
index 0fcb27685b0..fa90285387f 100644
---
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/WrapperFactoryDefault.java
+++
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/WrapperFactoryDefault.java
@@ -149,12 +149,6 @@ public void close() {
// -- WRAPPING
- @Override
- public <T> T wrap(
- final @NonNull T domainObject) {
- return wrap(domainObject, SyncControl.defaults());
- }
-
@Override
public <T> T wrap(
final @NonNull T domainObject,
@@ -169,13 +163,6 @@ public <T> T wrap(
return createProxy(domainObject, syncControl);
}
- @Override
- public <T> T wrapMixin(
- final @NonNull Class<T> mixinClass,
- final @NonNull Object mixee) {
- return wrapMixin(mixinClass, mixee, SyncControl.defaults());
- }
-
@Override
public <T> T wrapMixin(
final @NonNull Class<T> mixinClass,
diff --git
a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
index 7fbbf988dde..8193b62f7c2 100644
---
a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
+++
b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
@@ -40,7 +40,6 @@
import org.apache.causeway.applib.services.iactnlayer.InteractionService;
import org.apache.causeway.applib.services.wrapper.WrapperFactory;
import org.apache.causeway.applib.services.wrapper.WrapperFactory.AsyncProxy;
-import org.apache.causeway.applib.services.wrapper.control.AsyncControl;
import org.apache.causeway.applib.services.xactn.TransactionService;
import org.apache.causeway.core.config.environment.CausewaySystemEnvironment;
import org.apache.causeway.extensions.commandlog.applib.dom.BackgroundService;
@@ -115,28 +114,24 @@ void async_using_default_executor_service() {
transactionService.runTransactional(Propagation.REQUIRES_NEW, () -> {
var counter = bookmarkService.lookup(bookmark,
Counter.class).orElseThrow();
- var control = AsyncControl.defaults();
-
- asyncProxyUnderTest1.set(wrapperFactory.asyncWrap(counter,
control));
+ asyncProxyUnderTest1.set(wrapperFactory.asyncWrap(counter));
}).ifFailureFail();
// execute async and wait till done
{
asyncProxyUnderTest1.get()
- .thenApplyAsync(Counter::bumpUsingDeclaredAction)
- .orTimeout(5, TimeUnit.SECONDS)
- .join(); // wait till done
+ .applyAsync(Counter::bumpUsingDeclaredAction)
+ .tryGet(5, TimeUnit.SECONDS); // wait till done
}
// then
transactionService.runTransactional(Propagation.REQUIRES_NEW, () -> {
var counter = bookmarkService.lookup(bookmark,
Counter.class).orElseThrow();
assertThat(counter.getNum()).isEqualTo(1L);
- var control = AsyncControl.defaults();
// store the async proxy for later use below
-
asyncProxyUnderTest2.set(wrapperFactory.asyncWrapMixin(Counter_bumpUsingMixin.class,
counter, control));
+
asyncProxyUnderTest2.set(wrapperFactory.asyncWrapMixin(Counter_bumpUsingMixin.class,
counter));
}).ifFailureFail();
@@ -144,10 +139,10 @@ void async_using_default_executor_service() {
{
// returns the detached counter entity, so we can immediately
check whether the action was executed
var counter = asyncProxyUnderTest2.get()
- .thenApplyAsync(Counter_bumpUsingMixin::act)
+ .applyAsync(Counter_bumpUsingMixin::act)
// let's wait max 5 sec to allow executor to complete
before continuing
- .orTimeout(5, TimeUnit.SECONDS)
- .join(); // wait till done
+ .tryGet(5, TimeUnit.SECONDS)
+ .valueAsNonNullElseFail();
assertThat(counter.getNum()).isEqualTo(2L);
}
@@ -181,10 +176,9 @@ void using_background_service() {
// execute async and wait till done
{
asyncProxyUnderTest.get()
- .thenAcceptAsync(Counter::bumpUsingDeclaredAction)
+ .acceptAsync(Counter::bumpUsingDeclaredAction)
// let's wait max 5 sec to allow executor to complete before
continuing
- .orTimeout(5, TimeUnit.SECONDS)
- .join(); // wait till done
+ .tryGet(5, TimeUnit.SECONDS); // wait till done
}
// then no change to the counter
diff --git
a/regressiontests/base-jdo/src/main/java/org/apache/causeway/testdomain/jdo/publishing/PublishingTestFactoryJdo.java
b/regressiontests/base-jdo/src/main/java/org/apache/causeway/testdomain/jdo/publishing/PublishingTestFactoryJdo.java
index e48f9aa88ca..ed3d91b307a 100644
---
a/regressiontests/base-jdo/src/main/java/org/apache/causeway/testdomain/jdo/publishing/PublishingTestFactoryJdo.java
+++
b/regressiontests/base-jdo/src/main/java/org/apache/causeway/testdomain/jdo/publishing/PublishingTestFactoryJdo.java
@@ -365,12 +365,11 @@ protected void wrapperAsyncExecutionNoRules(
// when - running asynchronous
return wrapper.asyncWrap(book, asyncControl)
- .thenAcceptAsync(bk->bk.setName("Book #2"));
+ .acceptAsync(bk->bk.setName("Book #2"));
});
future
- .orTimeout(10, TimeUnit.SECONDS)
- .join(); // wait till done
+ .tryGet(10, TimeUnit.SECONDS); // wait till done
}
@Override
@@ -383,13 +382,13 @@ protected void wrapperAsyncExecutionWithRules(
context.runGiven();
- // when - running synchronous
+ // when - running asynchronous
var asyncControl = AsyncControl.defaults().withCheckRules(); //
enforce rules
//assertThrows(DisabledException.class, ()->{
// should fail with DisabledException (synchronous) within the
calling Thread
wrapper.asyncWrap(book, asyncControl)
- .thenAcceptAsync(bk->bk.setName("Book #2"));
+ .acceptAsync(bk->bk.setName("Book #2"));
//});
diff --git
a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java
b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java
index dfd7a5212c4..77805fae6c1 100644
---
a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java
+++
b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java
@@ -360,12 +360,11 @@ protected void wrapperAsyncExecutionNoRules(
// when - running asynchronous
return wrapper.asyncWrap(book, asyncControl)
- .thenAcceptAsync(bk->bk.setName("Book #2"));
+ .acceptAsync(bk->bk.setName("Book #2"));
});
future
- .orTimeout(10, TimeUnit.SECONDS)
- .join(); // wait till done
+ .tryGet(10, TimeUnit.SECONDS); // wait till done
}
@@ -375,16 +374,13 @@ protected void wrapperAsyncExecutionWithRules(
context.bind(commitListener);
- // when
+ // when enforce rules
withBookDo(book->{
- // when - running synchronous
- var asyncControl = AsyncControl.defaults().withCheckRules(); //
enforce rules
-
//assertThrows(DisabledException.class, ()->{
// should fail with DisabledException (synchronous) within the
calling Thread
- wrapper.asyncWrap(book, asyncControl)
- .thenAcceptAsync(bk->bk.setName("Book #2"));
+ wrapper.asyncWrap(book)
+ .acceptAsync(bk->bk.setName("Book #2"));
//});
diff --git
a/regressiontests/core-wrapperfactory/src/test/java/org/apache/causeway/regressiontests/core/wrapperfactory/integtests/WrapperFactory_async_IntegTest.java
b/regressiontests/core-wrapperfactory/src/test/java/org/apache/causeway/regressiontests/core/wrapperfactory/integtests/WrapperFactory_async_IntegTest.java
index 76df8059a4a..4284d616169 100644
---
a/regressiontests/core-wrapperfactory/src/test/java/org/apache/causeway/regressiontests/core/wrapperfactory/integtests/WrapperFactory_async_IntegTest.java
+++
b/regressiontests/core-wrapperfactory/src/test/java/org/apache/causeway/regressiontests/core/wrapperfactory/integtests/WrapperFactory_async_IntegTest.java
@@ -98,9 +98,9 @@ void async_using_default_executor_service(final String
displayName, final Execut
// execute async and wait till done
{
asyncProxyUnderTest1.get()
- .thenApplyAsync(Counter::increment)
- .orTimeout(5_000, TimeUnit.MILLISECONDS)
- .join(); // let's wait max 5 sec to allow executor to complete
before continuing
+ .applyAsync(Counter::increment)
+ // let's wait max 5 sec to allow executor to complete before
continuing
+ .tryGet(5, TimeUnit.SECONDS);
}
// then
@@ -125,10 +125,10 @@ void async_using_default_executor_service(final String
displayName, final Execut
{
// returns the detached counter entity, so we can immediately
check whether the action was executed
var counter = asyncProxyUnderTest2.get()
- .thenApplyAsync(Counter_bumpUsingMixin::act)
+ .applyAsync(Counter_bumpUsingMixin::act)
// let's wait max 5 sec to allow executor to complete
before continuing
- .orTimeout(5, TimeUnit.SECONDS)
- .join(); // wait till done
+ .tryGet(5, TimeUnit.SECONDS)
+ .valueAsNonNullElseFail();
assertThat(counter.getNum()).isEqualTo(2L);
}
diff --git
a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CommandArgumentTest.java
b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CommandArgumentTest.java
index 516def8849b..ab1f1bfbbb9 100644
---
a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CommandArgumentTest.java
+++
b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CommandArgumentTest.java
@@ -125,9 +125,9 @@ void listParam_shouldAllowAsyncInvocation() throws
InterruptedException, Executi
var control = AsyncControl.defaults();
var stringified = wrapperFactory.asyncWrap(commandArgDemo, control)
- .thenApplyAsync(commandResult->commandResult.list(List.of(1L, 2L,
3L)))
- .orTimeout(3L, TimeUnit.DAYS)
- .join() // wait till done
+ .applyAsync(commandResult->commandResult.list(List.of(1L, 2L, 3L)))
+ .tryGet(3L, TimeUnit.DAYS) // wait till done
+ .valueAsNonNullElseFail()
.getResultAsString();
assertEquals("[1, 2, 3]", stringified);
diff --git
a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/WrapperInteraction_Caching_IntegTest.java
b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/WrapperInteraction_Caching_IntegTest.java
index 53d1141fdc9..96b8e9c53ca 100644
---
a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/WrapperInteraction_Caching_IntegTest.java
+++
b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/WrapperInteraction_Caching_IntegTest.java
@@ -69,7 +69,6 @@ static class StatefulCalculator {
@Action
@RequiredArgsConstructor
public static class StatefulCalculator_add {
- @SuppressWarnings("unused")
private final StatefulCalculator mixee;
public Integer act(final int amount) {
return mixee.inc(amount);
@@ -119,17 +118,17 @@ void async_wrapped() throws ExecutionException,
InterruptedException, TimeoutExc
// when
var asyncControlForCalculator1 = AsyncControl.defaults();
var asyncCalculator1 = wrapperFactory.asyncWrap(calculator1,
asyncControlForCalculator1)
- .thenApplyAsync(calc->calc.inc(12));
+ .applyAsync(calc->calc.inc(12));
var asyncControlForCalculator2 = AsyncControl.defaults();
var asyncCalculator2 = wrapperFactory.asyncWrap(calculator2,
asyncControlForCalculator2)
- .thenApplyAsync(calc->calc.inc(24));
+ .applyAsync(calc->calc.inc(24));
// then
- Assertions.assertThat(asyncCalculator1.orTimeout(10,
TimeUnit.SECONDS).join().intValue()).isEqualTo(12);
+ Assertions.assertThat(asyncCalculator1.tryGet(10,
TimeUnit.SECONDS).valueAsNonNullElseFail().intValue()).isEqualTo(12);
Assertions.assertThat(calculator1.getTotal()).isEqualTo(12);
- Assertions.assertThat(asyncCalculator2.orTimeout(10,
TimeUnit.SECONDS).join().intValue()).isEqualTo(24);
+ Assertions.assertThat(asyncCalculator2.tryGet(10,
TimeUnit.SECONDS).valueAsNonNullElseFail().intValue()).isEqualTo(24);
Assertions.assertThat(calculator2.getTotal()).isEqualTo(24);
}