If the target method throws {@link java.lang.Error} dispatching terminates with + * rethrowing the error. + * + *
Other types of exceptions are converted to {@link io.spine.base.Error} and returned
+ * {@link DispatchOutcome.Builder#setError inside} the {@link DispatchOutcome}.
+ *
+ * @implNote The result of this method is not validated, as its fields in fact consist
* of the parts, such as wrapped {@code Command}s and {@code Event}s that are validated
- * upon their creation. Such an approach allows to improve the overall performance of
+ * upon their creation. Such an approach allows improving the overall performance of
* the signal propagation.
*/
+ @SuppressWarnings({
+ "ChainOfInstanceofChecks" /* We need to separate exceptions. */,
+ "ThrowInsideCatchBlockWhichIgnoresCaughtException", "ProhibitedExceptionThrown"
+ /* Rethrowing `Error`. See Javadoc. */
+ })
@Override
public DispatchOutcome invoke(T target, E envelope) {
checkNotNull(target);
@@ -301,7 +312,9 @@ public DispatchOutcome invoke(T target, E envelope) {
} catch (InvocationTargetException e) {
var cause = e.getCause();
checkNotNull(cause);
- if (cause instanceof RejectionThrowable) {
+ if (cause instanceof Error) {
+ throw (Error) cause;
+ } else if (cause instanceof RejectionThrowable) {
var success = asRejection(target, envelope, (RejectionThrowable) cause);
outcome.setSuccess(success);
} else {
@@ -340,10 +353,10 @@ protected Optional Default implementation does nothing. Descending classes may override for checking
- * the match.
+ * The default implementation does nothing.
+ * Descending classes may override for checking the match.
*
* @throws IllegalArgumentException
* the default implementation does not throw ever. Descending classes would throw
diff --git a/server/src/main/java/io/spine/server/model/IllegalOutcomeException.java b/server/src/main/java/io/spine/server/model/IllegalOutcomeException.java
index 9211187f08..95c3609aa6 100644
--- a/server/src/main/java/io/spine/server/model/IllegalOutcomeException.java
+++ b/server/src/main/java/io/spine/server/model/IllegalOutcomeException.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2022, TeamDev. All rights reserved.
+ * Copyright 2024, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
@@ -33,8 +33,8 @@
/**
* An exception signifying that a handler method produced an unexpected result.
*
- * For example, event subscriber methods should not produce any result signals. If any such
- * signals are encountered, an {@code IllegalOutcomeException} is thrown.
+ * For example, event subscriber methods should not produce any result signals.
+ * If any such signals are encountered, an {@code IllegalOutcomeException} is thrown.
*/
@Internal
public final class IllegalOutcomeException extends RuntimeException {
diff --git a/server/src/main/java/io/spine/server/stand/QueryValidator.java b/server/src/main/java/io/spine/server/stand/QueryValidator.java
index eeab621b7d..70b1b20965 100644
--- a/server/src/main/java/io/spine/server/stand/QueryValidator.java
+++ b/server/src/main/java/io/spine/server/stand/QueryValidator.java
@@ -100,6 +100,6 @@ protected InvalidRequestException unsupportedException(Query request, Error erro
@Override
protected String errorMessage(Query request) {
var targetType = getTypeOf(request.getTarget());
- return format("The query target type is not supported: %s", targetType.toTypeName());
+ return format("The query target type is not supported: %s", targetType.typeName());
}
}
diff --git a/server/src/main/java/io/spine/server/stand/TopicValidator.java b/server/src/main/java/io/spine/server/stand/TopicValidator.java
index 02782f7bdc..e86b8ce03b 100644
--- a/server/src/main/java/io/spine/server/stand/TopicValidator.java
+++ b/server/src/main/java/io/spine/server/stand/TopicValidator.java
@@ -85,6 +85,6 @@ protected InvalidRequestException unsupportedException(Topic request,
@Override
protected String errorMessage(Topic request) {
var targetType = getTypeOf(request.getTarget());
- return format("The topic target type is not supported: %s", targetType.toTypeName());
+ return format("The topic target type is not supported: %s", targetType.typeName());
}
}
diff --git a/server/src/test/java/io/spine/server/model/AbstractReceptorSpec.java b/server/src/test/java/io/spine/server/model/AbstractReceptorSpec.java
deleted file mode 100644
index 7ca02b597a..0000000000
--- a/server/src/test/java/io/spine/server/model/AbstractReceptorSpec.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2022, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.server.model;
-
-import io.spine.core.Event;
-import io.spine.server.model.given.method.OneParamMethod;
-import io.spine.server.model.given.method.OneParamSignature;
-import io.spine.server.model.given.method.OneParamSpec;
-import io.spine.server.model.given.method.StubHandler;
-import io.spine.server.model.given.method.TwoParamMethod;
-import io.spine.server.model.given.method.TwoParamSpec;
-import io.spine.server.type.EventEnvelope;
-import io.spine.server.type.given.GivenEvent;
-import io.spine.test.model.ModProjectCreated;
-import io.spine.test.model.ModProjectStarted;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-import static io.spine.base.Identifier.newUuid;
-import static io.spine.protobuf.AnyPacker.pack;
-import static io.spine.server.model.AbstractReceptor.firstParamType;
-import static io.spine.server.model.given.method.StubHandler.getMethodWithCheckedException;
-import static io.spine.server.model.given.method.StubHandler.getMethodWithRuntimeException;
-import static io.spine.testing.TestValues.nullRef;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-@DisplayName("`AbstractReceptor` should")
-@SuppressWarnings("DuplicateStringLiteralInspection") // Common test display names.
-class AbstractReceptorSpec {
-
- private final OneParamSignature signature = new OneParamSignature();
-
- private TwoParamMethod twoParamMethod;
- private OneParamMethod oneParamMethod;
-
- private Object target;
-
- @BeforeEach
- void setUp() {
- target = new StubHandler();
- twoParamMethod = new TwoParamMethod(StubHandler.getTwoParameterMethod(),
- TwoParamSpec.INSTANCE);
- oneParamMethod = new OneParamMethod(StubHandler.getOneParameterMethod(),
- OneParamSpec.INSTANCE);
- }
-
- @Test
- @DisplayName("not accept `null` method")
- void notAcceptNullMethod() {
- assertThrows(NullPointerException.class, () -> new TwoParamMethod(nullRef(),
- TwoParamSpec.INSTANCE));
- }
-
- @Test
- @DisplayName("return method")
- void returnMethod() {
- assertEquals(StubHandler.getTwoParameterMethod(), twoParamMethod.rawMethod());
- }
-
- @Nested
- @DisplayName("check if method access is")
- class CheckAccess {
-
- @Test
- @DisplayName(AccessModifier.MODIFIER_PUBLIC)
- void isPublic() {
- assertTrue(twoParamMethod.isPublic());
- }
-
- @Test
- @DisplayName(AccessModifier.MODIFIER_PRIVATE)
- void isPrivate() {
- assertTrue(oneParamMethod.isPrivate());
- }
- }
-
- @Test
- @DisplayName("obtain first parameter type of method")
- void returnFirstParamType() {
- assertEquals(ModProjectStarted.class, firstParamType(oneParamMethod.rawMethod()));
- }
-
- @Nested
- @DisplayName("invoke method")
- class InvokeMethod {
-
- @SuppressWarnings("CheckReturnValue") // can ignore the result in this test
- @Test
- @DisplayName("with one parameter")
- void withOneParam() {
- var eventMessage = ModProjectStarted.newBuilder()
- .setId(newUuid())
- .build();
- var event = Event.newBuilder()
- .setId(GivenEvent.someId())
- .setMessage(pack(eventMessage))
- .setContext(GivenEvent.context())
- .build();
- var envelope = EventEnvelope.of(event);
- oneParamMethod.invoke(target, envelope);
-
- assertTrue(((StubHandler) target).wasHandleInvoked());
- }
-
- @Test
- @DisplayName("with two parameters")
- @SuppressWarnings("CheckReturnValue") // can ignore the result in this test
- void withTwoParams() {
- var eventMessage = ModProjectCreated.newBuilder()
- .setId(newUuid())
- .build();
- var event = Event.newBuilder()
- .setId(GivenEvent.someId())
- .setMessage(pack(eventMessage))
- .setContext(GivenEvent.context())
- .build();
- var envelope = EventEnvelope.of(event);
- twoParamMethod.invoke(target, envelope);
-
- assertTrue(((StubHandler) target).wasOnInvoked());
- }
- }
-
- @Test
- @DisplayName("return full name in `toString`")
- void provideToString() {
- assertEquals(twoParamMethod.getFullName(), twoParamMethod.toString());
- }
-
- @Nested
- @DisplayName("provide `equals` method such that")
- class ProvideEqualsSuchThat {
-
- @Test
- @DisplayName("instance equals to itself")
- void equalsToItself() {
- assertEquals(twoParamMethod, twoParamMethod);
- }
-
- @Test
- @DisplayName("instance is not equal to `null`")
- void notEqualsToNull() {
- assertNotEquals(null, oneParamMethod);
- }
-
- @Test
- @DisplayName("instance is not equal to another class")
- void notEqualsToOtherClass() {
- assertNotEquals(twoParamMethod, oneParamMethod);
- }
-
- @Test
- @DisplayName("all fields are compared")
- void allFieldsAreCompared() {
- AbstractReceptor, ?, ?, ?, ?> anotherMethod =
- new TwoParamMethod(StubHandler.getTwoParameterMethod(),
- TwoParamSpec.INSTANCE);
- assertEquals(twoParamMethod, anotherMethod);
- }
- }
-
- @Test
- @DisplayName("have `hashCode`")
- void haveHashCode() {
- assertNotEquals(System.identityHashCode(twoParamMethod), twoParamMethod.hashCode());
- }
-
- @Nested
- @DisplayName("not be created from method throwing")
- class RejectMethodThrowing {
-
- @Test
- @DisplayName("checked exception")
- void checkedException() {
- var method = signature.classify(getMethodWithCheckedException());
- assertFalse(method.isPresent());
- }
-
- @Test
- @DisplayName("runtime exception")
- void runtimeException() {
- var method = signature.classify(getMethodWithRuntimeException());
- assertFalse(method.isPresent());
- }
- }
-}
diff --git a/server/src/test/java/io/spine/server/model/given/method/StubHandler.java b/server/src/test/java/io/spine/server/model/given/method/StubHandler.java
index 2d3ccc42df..81bdf21bca 100644
--- a/server/src/test/java/io/spine/server/model/given/method/StubHandler.java
+++ b/server/src/test/java/io/spine/server/model/given/method/StubHandler.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2022, TeamDev. All rights reserved.
+ * Copyright 2024, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
@@ -34,17 +34,18 @@
import java.io.IOException;
import java.lang.reflect.Method;
-@SuppressWarnings("UnusedParameters") // OK for test methods.
public class StubHandler {
private boolean onInvoked;
private boolean handleInvoked;
- private static void throwCheckedException(BoolValue message) throws Exception {
+ private static void throwCheckedException(
+ @SuppressWarnings("unused") BoolValue message) throws Exception {
throw new IOException("Throw new checked exception");
}
- private static void throwRuntimeException(BoolValue message) throws RuntimeException {
+ private static void throwRuntimeException(
+ @SuppressWarnings("unused") BoolValue message) throws RuntimeException {
throw new RuntimeException("Throw new runtime exception");
}
@@ -92,6 +93,7 @@ public static Method getMethodWithRuntimeException() {
return method;
}
+ @SuppressWarnings("unused" /* to declare a method with two params. */)
public void on(ModProjectCreated message, EventContext context) {
onInvoked = true;
}
diff --git a/server/src/test/java/io/spine/system/server/given/SystemContextSettingsTestEnv.java b/server/src/test/java/io/spine/system/server/given/SystemContextSettingsTestEnv.java
index f5a7a2f352..a8e335e39e 100644
--- a/server/src/test/java/io/spine/system/server/given/SystemContextSettingsTestEnv.java
+++ b/server/src/test/java/io/spine/system/server/given/SystemContextSettingsTestEnv.java
@@ -65,7 +65,8 @@ public static MemoizingObserver