Skip to content

Commit

Permalink
Merge pull request #1295 from SpineEventEngine/improve-command-filter…
Browse files Browse the repository at this point in the history
…-rejections-support

Improve support of rejections thrown from the `CommandBus` filters
  • Loading branch information
dmitrykuzmin committed Sep 1, 2020
2 parents 86aaa54 + e4e7f78 commit 56204a2
Show file tree
Hide file tree
Showing 42 changed files with 1,414 additions and 221 deletions.
60 changes: 60 additions & 0 deletions client/src/main/java/io/spine/grpc/CompositeObserver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2020, TeamDev. All rights reserved.
*
* 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.grpc;

import com.google.common.collect.ImmutableList;
import io.grpc.stub.StreamObserver;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* A stream observer which delegates calls to multiple other observers with the same target type.
*
* <p>The observers are called in the exact same order in which they are specified on the object
* construction.
*
* @param <T>
* the observed type
*/
public final class CompositeObserver<T> implements StreamObserver<T> {

private final ImmutableList<StreamObserver<? super T>> observers;

public CompositeObserver(Iterable<StreamObserver<? super T>> observers) {
checkNotNull(observers);
this.observers = ImmutableList.copyOf(observers);
}

@Override
public void onNext(T value) {
observers.forEach(o -> o.onNext(value));
}

@Override
public void onError(Throwable t) {
observers.forEach(o -> o.onError(t));
}

@Override
public void onCompleted() {
observers.forEach(StreamObserver::onCompleted);
}
}
84 changes: 84 additions & 0 deletions client/src/test/java/io/spine/grpc/CompositeObserverTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2020, TeamDev. All rights reserved.
*
* 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.grpc;

import com.google.common.collect.ImmutableList;
import com.google.common.testing.NullPointerTester;
import io.grpc.stub.StreamObserver;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static com.google.common.truth.Truth.assertThat;

@DisplayName("`CompositeObserver` should")
class CompositeObserverTest {

@Test
@DisplayName("not accept `null` observer list on construction")
void passNullToleranceCheck() {
new NullPointerTester()
.testAllPublicConstructors(CompositeObserver.class);
}

@Test
@DisplayName("delegate `onNext` calls to wrapped observers")
void delegateOnNext() {
MemoizingObserver<String> observer1 = StreamObservers.memoizingObserver();
MemoizingObserver<String> observer2 = StreamObservers.memoizingObserver();
StreamObserver<String> observer =
new CompositeObserver<>(ImmutableList.of(observer1, observer2));

String value = "String value.";
observer.onNext(value);

assertThat(observer1.firstResponse()).isEqualTo(value);
assertThat(observer2.firstResponse()).isEqualTo(value);
}

@Test
@DisplayName("delegate `onError` calls to wrapped observers")
void delegateOnError() {
MemoizingObserver<String> observer1 = StreamObservers.memoizingObserver();
MemoizingObserver<String> observer2 = StreamObservers.memoizingObserver();
StreamObserver<String> observer =
new CompositeObserver<>(ImmutableList.of(observer1, observer2));

RuntimeException error = new RuntimeException("An error.");
observer.onError(error);

assertThat(observer1.getError()).isEqualTo(error);
assertThat(observer2.getError()).isEqualTo(error);
}

@Test
@DisplayName("delegate `onCompleted` calls to wrapped observers")
void delegateOnCompleted() {
MemoizingObserver<String> observer1 = StreamObservers.memoizingObserver();
MemoizingObserver<String> observer2 = StreamObservers.memoizingObserver();
StreamObserver<String> observer =
new CompositeObserver<>(ImmutableList.of(observer1, observer2));

observer.onCompleted();

assertThat(observer1.isCompleted()).isTrue();
assertThat(observer2.isCompleted()).isTrue();
}
}
32 changes: 16 additions & 16 deletions license-report.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


# Dependencies of `io.spine:spine-client:1.5.25`
# Dependencies of `io.spine:spine-client:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -406,12 +406,12 @@
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:45:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:45:57 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine:spine-core:1.5.25`
# Dependencies of `io.spine:spine-core:1.5.27`

## Runtime
1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2
Expand Down Expand Up @@ -777,12 +777,12 @@ This report was generated on **Tue Aug 18 15:45:58 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:45:59 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:45:57 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine.tools:spine-model-assembler:1.5.25`
# Dependencies of `io.spine.tools:spine-model-assembler:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -1183,12 +1183,12 @@ This report was generated on **Tue Aug 18 15:45:59 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:00 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:45:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine.tools:spine-model-verifier:1.5.25`
# Dependencies of `io.spine.tools:spine-model-verifier:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -1659,12 +1659,12 @@ This report was generated on **Tue Aug 18 15:46:00 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:00 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:45:59 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine:spine-server:1.5.25`
# Dependencies of `io.spine:spine-server:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -2082,12 +2082,12 @@ This report was generated on **Tue Aug 18 15:46:00 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:01 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:45:59 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine:spine-testutil-client:1.5.25`
# Dependencies of `io.spine:spine-testutil-client:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -2542,12 +2542,12 @@ This report was generated on **Tue Aug 18 15:46:01 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:04 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:46:01 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine:spine-testutil-core:1.5.25`
# Dependencies of `io.spine:spine-testutil-core:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -3010,12 +3010,12 @@ This report was generated on **Tue Aug 18 15:46:04 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:05 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:46:02 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).




# Dependencies of `io.spine:spine-testutil-server:1.5.25`
# Dependencies of `io.spine:spine-testutil-server:1.5.27`

## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
Expand Down Expand Up @@ -3514,4 +3514,4 @@ This report was generated on **Tue Aug 18 15:46:05 EEST 2020** using [Gradle-Lic
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.


This report was generated on **Tue Aug 18 15:46:08 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
This report was generated on **Mon Aug 31 12:46:05 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
22 changes: 11 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ all modules and does not describe the project structure per-subproject.

<groupId>io.spine</groupId>
<artifactId>spine-core-java</artifactId>
<version>1.5.25</version>
<version>1.5.27</version>

<inceptionYear>2015</inceptionYear>

Expand Down Expand Up @@ -70,25 +70,25 @@ all modules and does not describe the project structure per-subproject.
<dependency>
<groupId>io.spine</groupId>
<artifactId>spine-base</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.spine</groupId>
<artifactId>spine-time</artifactId>
<version>1.5.21</version>
<version>1.5.24</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-model-compiler</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-plugin-base</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -130,25 +130,25 @@ all modules and does not describe the project structure per-subproject.
<dependency>
<groupId>io.spine</groupId>
<artifactId>spine-testlib</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.spine</groupId>
<artifactId>spine-testutil-time</artifactId>
<version>1.5.21</version>
<version>1.5.24</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-mute-logging</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-plugin-testlib</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -204,12 +204,12 @@ all modules and does not describe the project structure per-subproject.
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-javadoc-filter</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
</dependency>
<dependency>
<groupId>io.spine.tools</groupId>
<artifactId>spine-protoc-plugin</artifactId>
<version>1.5.23</version>
<version>1.5.29</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/io/spine/server/BoundedContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ protected final void init() {
eventBus.registerWith(this);
tenantIndex.registerWith(this);
broker.registerWith(this);
commandBus.initObservers(eventBus);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ public BoundedContextBuilder addCommandDispatcher(CommandDispatcher commandDispa
* <p>The order of appending the filters to the builder is the order of the filters in
* the {@code CommandBus}.
*/
@CanIgnoreReturnValue
public BoundedContextBuilder addCommandFilter(BusFilter<CommandEnvelope> filter) {
checkNotNull(filter);
commandBus.appendFilter(filter);
Expand Down Expand Up @@ -321,6 +322,7 @@ public BoundedContextBuilder addEventDispatcher(EventDispatcher eventDispatcher)
* @param filter
* the filter to add
*/
@CanIgnoreReturnValue
public BoundedContextBuilder addEventFilter(BusFilter<EventEnvelope> filter) {
checkNotNull(filter);
eventBus.appendFilter(filter);
Expand Down Expand Up @@ -656,7 +658,9 @@ public BoundedContextBuilder testingCopy() {
copy.enrichEventsUsing(enricher);
repositories().forEach(copy::add);
commandDispatchers().forEach(copy::addCommandDispatcher);
commandBus.filters().forEach(copy::addCommandFilter);
eventDispatchers().forEach(copy::addEventDispatcher);
eventBus.filters().forEach(copy::addEventFilter);
return copy;
}
}
2 changes: 1 addition & 1 deletion server/src/main/java/io/spine/server/CommandService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import java.util.Map;
import java.util.Set;

import static io.spine.server.bus.Buses.reject;
import static io.spine.server.bus.Acks.reject;

/**
* The {@code CommandService} allows client applications to post commands and
Expand Down
Loading

0 comments on commit 56204a2

Please sign in to comment.