Throw DaprException consistently + doc + example. (#403)

This commit is contained in:
Artur Souza 2020-12-08 15:58:07 -08:00 committed by GitHub
parent 16faa43795
commit adce91f743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1210 additions and 357 deletions

View File

@ -26,7 +26,7 @@ jobs:
DAPR_RUNTIME_VER: 1.0.0-rc.1 DAPR_RUNTIME_VER: 1.0.0-rc.1
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/a60221e96406a145ab22e454eec6642961725f5c/install/install.sh DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/a60221e96406a145ab22e454eec6642961725f5c/install/install.sh
DAPR_CLI_REF: DAPR_CLI_REF:
DAPR_REF: 83f5c45362b0c577139b1887276d7cf1b7308506 DAPR_REF: 79688c8ce802b3b31382da97422db63a27821599
OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }} OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }}
OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }} OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }}
GPG_KEY: ${{ secrets.GPG_KEY }} GPG_KEY: ${{ secrets.GPG_KEY }}

View File

@ -144,6 +144,7 @@ Try the following examples to learn more about Dapr's Java SDK:
* [Actors over Http](./examples/src/main/java/io/dapr/examples/actors/http) * [Actors over Http](./examples/src/main/java/io/dapr/examples/actors/http)
* [Secrets management](./examples/src/main/java/io/dapr/examples/secrets) * [Secrets management](./examples/src/main/java/io/dapr/examples/secrets)
* [Distributed tracing with OpenTelemetry SDK](./examples/src/main/java/io/dapr/examples/tracing) * [Distributed tracing with OpenTelemetry SDK](./examples/src/main/java/io/dapr/examples/tracing)
* [Exception handling](./examples/src/main/java/io/dapr/examples/exception)
#### API Documentation #### API Documentation
@ -221,30 +222,12 @@ Now you can go to your IDE (like Eclipse, for example) and debug your Java appli
Calls to Dapr's APIs on `http://127.0.0.1:3500/*` should work now and trigger breakpoints in your code. Calls to Dapr's APIs on `http://127.0.0.1:3500/*` should work now and trigger breakpoints in your code.
#### Creating and publishing the artifacts to Nexus Repository #### Exception handling
In case you need to publish Dapr's SDK to a private Nexus repo, run the command below from the project's root directory:
```sh All exceptions thrown from the SDK are instances of `DaprException`. `DaprException` extends from `RuntimeException`, making it compatible with Project Reactor. See [example](./examples/src/main/java/io/dapr/examples/exception) for more details.
mvn package
mvn deploy:deploy-file -DgeneratePom=false -DrepositoryId=nexus -Durl=http://localhost:8081/repository/maven-releases -DpomFile=pom.xml -Dfile=target/dapr-sdk-0.3.0.jar
```
For more documentation reference:
https://maven.apache.org/plugins/maven-deploy-plugin
https://help.sonatype.com/repomanager3/user-interface/uploading-components
### Development ### Development
#### Maven Module version management
When releasing a new version of this SDK you must increase the version of all modules and pom files, so run the following commands:
```sh
mvn versions:set -DnewVersion="0.1.0-preview02"
mvn versions:commit
```
#### Update proto files #### Update proto files
Change the properties below in [pom.xml](./pom.xml) to point to the desired reference URL in Git. Avoid pointing to master branch since it can change over time and create unpredictable behavior in the build. Change the properties below in [pom.xml](./pom.xml) to point to the desired reference URL in Git. Avoid pointing to master branch since it can change over time and create unpredictable behavior in the build.

View File

@ -8,8 +8,6 @@ package io.dapr.examples.bindings.http;
import io.dapr.client.DaprClient; import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientBuilder;
import java.io.IOException;
/** /**
* Service for output binding example. * Service for output binding example.
* 1. From your repo root, build and install jars: * 1. From your repo root, build and install jars:
@ -38,7 +36,7 @@ public class OutputBindingExample {
* @param args Not used. * @param args Not used.
*/ */
@SuppressWarnings("checkstyle:AbbreviationAsWordInName") @SuppressWarnings("checkstyle:AbbreviationAsWordInName")
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
int count = 0; int count = 0;

View File

@ -109,7 +109,7 @@ public class OutputBindingExample{
static final String BINDING_OPERATION = "create"; static final String BINDING_OPERATION = "create";
///... ///...
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
int count = 0; int count = 0;

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
package io.dapr.examples.exception;
import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder;
import io.dapr.exceptions.DaprException;
/**
* 1. Build and install jars:
* mvn clean install
* 2. Go into examples:
* cd examples
* 3. send a message to be saved as state:
* dapr run --components-path ./components --dapr-http-port 3006 -- \
* java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.exception.Client
*/
public class Client {
/**
* Executes the sate actions.
* @param args messages to be sent as state value.
*/
public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) {
try {
client.getState("Unknown state store", "myKey", String.class).block();
} catch (DaprException exception) {
System.out.println("Error code: " + exception.getErrorCode());
System.out.println("Error message: " + exception.getMessage());
exception.printStackTrace();
}
System.out.println("Done");
}
}
}

View File

@ -0,0 +1,68 @@
## Exception handling sample
This sample illustrates how to handle exceptions in Dapr.
## Pre-requisites
* [Dapr and Dapr Cli](https://docs.dapr.io/getting-started/install-dapr/).
* Java JDK 11 (or greater): [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11) or [OpenJDK](https://jdk.java.net/13/).
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
### Checking out the code
Clone this repository:
```sh
git clone https://github.com/dapr/java-sdk.git
cd java-sdk
```
Then build the Maven project:
```sh
# make sure you are in the `java-sdk` directory.
mvn install
```
Then get into the examples directory:
```sh
cd examples
```
### Running the StateClient
This example uses the Java SDK Dapr client in order perform an invalid operartion, causing Dapr runtime to return an error. See the code snippet bellow:
```java
public class Client {
public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) {
try {
client.getState("Unknown state store", "myKey", String.class).block();
} catch (DaprException exception) {
System.out.println("Error code: " + exception.getErrorCode());
System.out.println("Error message: " + exception.getMessage());
exception.printStackTrace();
}
System.out.println("Done");
}
}
}
```
The code uses the `DaprClient` created by the `DaprClientBuilder`. It tries to get a state from state store but provides an unknown state store. It causes Dapr sidecar to return error, which is converted to a `DaprException` to the application. To be compatible with Project Reactor, `DaprException` extends from `RuntimeException` - making it an unchecked exception.
The Dapr client is also within a try-with-resource block to properly close the client at the end.
### Running the example
Run this example with the following command:
```sh
dapr run --components-path ./components --dapr-http-port 3006 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.exception.Client
```
Once running, the OutputBindingExample should print the output as follows:
![stateouput](../../../../../resources/img/exception.png)

View File

@ -9,8 +9,6 @@ import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientBuilder;
import io.dapr.client.domain.HttpExtension; import io.dapr.client.domain.HttpExtension;
import java.io.IOException;
/** /**
* 1. Build and install jars: * 1. Build and install jars:
* mvn clean install * mvn clean install
@ -25,7 +23,7 @@ public class HelloWorldClient {
* *
* @param args Array of messages to be sent. * @param args Array of messages to be sent.
*/ */
public static void main(String[] args) throws InterruptedException, IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
String serviceAppId = "hellogrpc"; String serviceAppId = "hellogrpc";

View File

@ -86,7 +86,7 @@ The other component is the client. It will send one message per second to the se
```java ```java
private static class HelloWorldClient { private static class HelloWorldClient {
///... ///...
public static void main(String[] args) { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
String serviceAppId = "hellogrpc"; String serviceAppId = "hellogrpc";

View File

@ -9,8 +9,6 @@ import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientBuilder;
import io.dapr.client.domain.HttpExtension; import io.dapr.client.domain.HttpExtension;
import java.io.IOException;
/** /**
* 1. Build and install jars: * 1. Build and install jars:
* mvn clean install * mvn clean install
@ -31,7 +29,7 @@ public class InvokeClient {
* *
* @param args Messages to be sent as request for the invoke API. * @param args Messages to be sent as request for the invoke API.
*/ */
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = (new DaprClientBuilder()).build()) { try (DaprClient client = (new DaprClientBuilder()).build()) {
for (String message : args) { for (String message : args) {
byte[] response = client.invokeService(SERVICE_APP_ID, "say", message, HttpExtension.POST, null, byte[] response = client.invokeService(SERVICE_APP_ID, "say", message, HttpExtension.POST, null,

View File

@ -110,7 +110,7 @@ public class InvokeClient {
private static final String SERVICE_APP_ID = "invokedemo"; private static final String SERVICE_APP_ID = "invokedemo";
///... ///...
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = (new DaprClientBuilder()).build()) { try (DaprClient client = (new DaprClientBuilder()).build()) {
for (String message : args) { for (String message : args) {
byte[] response = client.invokeService(SERVICE_APP_ID, "say", message, HttpExtension.POST, null, byte[] response = client.invokeService(SERVICE_APP_ID, "say", message, HttpExtension.POST, null,

View File

@ -41,7 +41,7 @@ public class StateClient {
private static final String SECOND_KEY_NAME = "myKey2"; private static final String SECOND_KEY_NAME = "myKey2";
///... ///...
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
String message = args.length == 0 ? " " : args[0]; String message = args.length == 0 ? " " : args[0];

View File

@ -11,7 +11,6 @@ import io.dapr.client.domain.State;
import io.dapr.client.domain.TransactionalStateOperation; import io.dapr.client.domain.TransactionalStateOperation;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -45,7 +44,7 @@ public class StateClient {
* Executes the sate actions. * Executes the sate actions.
* @param args messages to be sent as state value. * @param args messages to be sent as state value.
*/ */
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
String message = args.length == 0 ? " " : args[0]; String message = args.length == 0 ? " " : args[0];

View File

@ -18,8 +18,6 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.OpenTelemetrySdk;
import java.io.IOException;
/** /**
* 1. Build and install jars: * 1. Build and install jars:
* mvn clean install * mvn clean install
@ -40,7 +38,7 @@ public class InvokeClient {
* *
* @param args Messages to be sent as request for the invoke API. * @param args Messages to be sent as request for the invoke API.
*/ */
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
Tracer tracer = OpenTelemetryConfig.createTracer(InvokeClient.class.getCanonicalName()); Tracer tracer = OpenTelemetryConfig.createTracer(InvokeClient.class.getCanonicalName());
Span span = tracer.spanBuilder("Example's Main").setSpanKind(Span.Kind.CLIENT).startSpan(); Span span = tracer.spanBuilder("Example's Main").setSpanKind(Span.Kind.CLIENT).startSpan();

View File

@ -140,7 +140,7 @@ public class InvokeClient {
private static final String SERVICE_APP_ID = "invokedemo"; private static final String SERVICE_APP_ID = "invokedemo";
///... ///...
public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception {
Tracer tracer = OpenTelemetryConfig.createTracer(InvokeClient.class.getCanonicalName()); Tracer tracer = OpenTelemetryConfig.createTracer(InvokeClient.class.getCanonicalName());
Span span = tracer.spanBuilder("Example's Main").setSpanKind(Span.Kind.CLIENT).startSpan(); Span span = tracer.spanBuilder("Example's Main").setSpanKind(Span.Kind.CLIENT).startSpan();

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

View File

@ -18,6 +18,8 @@ import io.grpc.ManagedChannelBuilder;
import java.io.Closeable; import java.io.Closeable;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import static io.dapr.exceptions.DaprException.throwIllegalArgumentException;
/** /**
* Builder to generate an ActorProxy instance. Builder can be reused for multiple instances. * Builder to generate an ActorProxy instance. Builder can be reused for multiple instances.
*/ */
@ -74,10 +76,10 @@ public class ActorProxyBuilder<T> implements Closeable {
*/ */
public ActorProxyBuilder(String actorType, Class<T> actorTypeClass) { public ActorProxyBuilder(String actorType, Class<T> actorTypeClass) {
if ((actorType == null) || actorType.isEmpty()) { if ((actorType == null) || actorType.isEmpty()) {
throw new IllegalArgumentException("ActorType is required."); throwIllegalArgumentException("ActorType is required.");
} }
if (actorTypeClass == null) { if (actorTypeClass == null) {
throw new IllegalArgumentException("ActorTypeClass is required."); throwIllegalArgumentException("ActorTypeClass is required.");
} }
this.useGrpc = Properties.USE_GRPC.get(); this.useGrpc = Properties.USE_GRPC.get();
@ -96,7 +98,7 @@ public class ActorProxyBuilder<T> implements Closeable {
*/ */
public ActorProxyBuilder<T> withObjectSerializer(DaprObjectSerializer objectSerializer) { public ActorProxyBuilder<T> withObjectSerializer(DaprObjectSerializer objectSerializer) {
if (objectSerializer == null) { if (objectSerializer == null) {
throw new IllegalArgumentException("Serializer is required."); throwIllegalArgumentException("Serializer is required.");
} }
this.objectSerializer = objectSerializer; this.objectSerializer = objectSerializer;
@ -111,7 +113,7 @@ public class ActorProxyBuilder<T> implements Closeable {
*/ */
public T build(ActorId actorId) { public T build(ActorId actorId) {
if (actorId == null) { if (actorId == null) {
throw new IllegalArgumentException("Cannot instantiate an Actor without Id."); throwIllegalArgumentException("Cannot instantiate an Actor without Id.");
} }
ActorProxyImpl proxy = new ActorProxyImpl( ActorProxyImpl proxy = new ActorProxyImpl(
@ -167,7 +169,7 @@ public class ActorProxyBuilder<T> implements Closeable {
int port = Properties.GRPC_PORT.get(); int port = Properties.GRPC_PORT.get();
if (port <= 0) { if (port <= 0) {
throw new IllegalStateException("Invalid port."); throwIllegalArgumentException("Invalid port.");
} }
return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port).usePlaintext().build(); return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port).usePlaintext().build();

View File

@ -7,6 +7,7 @@ package io.dapr.actors.client;
import io.dapr.actors.ActorId; import io.dapr.actors.ActorId;
import io.dapr.actors.ActorMethod; import io.dapr.actors.ActorMethod;
import io.dapr.exceptions.DaprException;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.utils.TypeRef; import io.dapr.utils.TypeRef;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -173,7 +174,8 @@ class ActorProxyImpl implements ActorProxy, InvocationHandler {
try { try {
return this.serializer.deserialize(response, type); return this.serializer.deserialize(response, type);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); DaprException.wrap(e);
return null;
} }
} }
@ -188,7 +190,8 @@ class ActorProxyImpl implements ActorProxy, InvocationHandler {
try { try {
return this.serializer.serialize(request); return this.serializer.serialize(request);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); DaprException.wrap(e);
return null;
} }
} }
} }

View File

@ -7,10 +7,14 @@ package io.dapr.actors.client;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import io.dapr.exceptions.DaprException;
import io.dapr.v1.DaprGrpc; import io.dapr.v1.DaprGrpc;
import io.dapr.v1.DaprProtos; import io.dapr.v1.DaprProtos;
import io.opentelemetry.context.Context;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.concurrent.Callable;
/** /**
* A DaprClient over GRPC for Actor. * A DaprClient over GRPC for Actor.
*/ */
@ -37,7 +41,7 @@ class DaprGrpcClient implements DaprClient {
*/ */
@Override @Override
public Mono<byte[]> invokeActorMethod(String actorType, String actorId, String methodName, byte[] jsonPayload) { public Mono<byte[]> invokeActorMethod(String actorType, String actorId, String methodName, byte[] jsonPayload) {
return Mono.fromCallable(() -> { return Mono.fromCallable(DaprException.wrap(() -> {
DaprProtos.InvokeActorRequest req = DaprProtos.InvokeActorRequest req =
DaprProtos.InvokeActorRequest.newBuilder() DaprProtos.InvokeActorRequest.newBuilder()
.setActorType(actorType) .setActorType(actorType)
@ -46,8 +50,17 @@ class DaprGrpcClient implements DaprClient {
.setData(jsonPayload == null ? ByteString.EMPTY : ByteString.copyFrom(jsonPayload)) .setData(jsonPayload == null ? ByteString.EMPTY : ByteString.copyFrom(jsonPayload))
.build(); .build();
ListenableFuture<DaprProtos.InvokeActorResponse> futureResponse = client.invokeActor(req); return get(client.invokeActor(req));
return futureResponse.get(); })).map(r -> r.getData().toByteArray());
}).map(r -> r.getData().toByteArray()); }
private static <V> V get(ListenableFuture<V> future) {
try {
return future.get();
} catch (Exception e) {
DaprException.wrap(e);
}
return null;
} }
} }

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
package io.dapr.actors;
import io.dapr.exceptions.DaprException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
public final class TestUtils {
private TestUtils() {}
public static <T extends Throwable> void assertThrowsDaprException(Class<T> expectedType, Executable executable) {
Throwable cause = Assertions.assertThrows(DaprException.class, executable).getCause();
Assertions.assertNotNull(cause);
Assertions.assertEquals(expectedType, cause.getClass());
}
public static void assertThrowsDaprException(String expectedErrorCode, Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNull(daprException.getCause());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
}
public static void assertThrowsDaprException(
String expectedErrorCode,
String expectedErrorMessage,
Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNull(daprException.getCause());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
}
public static <T extends Throwable> void assertThrowsDaprException(
Class<T> expectedType,
String expectedErrorCode,
String expectedErrorMessage,
Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNotNull(daprException.getCause());
Assertions.assertEquals(expectedType, daprException.getCause().getClass());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
}
}

View File

@ -7,33 +7,34 @@ package io.dapr.actors.client;
import io.dapr.actors.ActorId; import io.dapr.actors.ActorId;
import io.dapr.actors.ActorType; import io.dapr.actors.ActorType;
import io.dapr.exceptions.DaprException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class ActorProxyBuilderTest { public class ActorProxyBuilderTest {
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void buildWithNullActorId() { public void buildWithNullActorId() {
new ActorProxyBuilder("test", Object.class) new ActorProxyBuilder("test", Object.class)
.build(null); .build(null);
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void buildWithEmptyActorType() { public void buildWithEmptyActorType() {
new ActorProxyBuilder("", Object.class) new ActorProxyBuilder("", Object.class)
.build(new ActorId("100")); .build(new ActorId("100"));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void buildWithNullActorType() { public void buildWithNullActorType() {
new ActorProxyBuilder(null, Object.class) new ActorProxyBuilder(null, Object.class)
.build(new ActorId("100")); .build(new ActorId("100"));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void buildWithNullSerializer() { public void buildWithNullSerializer() {
new ActorProxyBuilder("MyActor", Object.class) new ActorProxyBuilder("MyActor", Object.class)
.withObjectSerializer(null) .withObjectSerializer(null)

View File

@ -7,6 +7,7 @@ package io.dapr.actors.client;
import io.dapr.actors.ActorId; import io.dapr.actors.ActorId;
import io.dapr.actors.ActorMethod; import io.dapr.actors.ActorMethod;
import io.dapr.exceptions.DaprException;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.serializer.DefaultObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer;
import org.junit.Assert; import org.junit.Assert;
@ -309,7 +310,7 @@ public class ActorProxyImplTest {
} }
@Test(expected = RuntimeException.class) @Test(expected = DaprException.class)
public void invokeActorMethodSavingDataWithIncorrectReturnType() { public void invokeActorMethodSavingDataWithIncorrectReturnType() {
final DaprClient daprClient = mock(DaprClient.class); final DaprClient daprClient = mock(DaprClient.class);
when(daprClient.invokeActorMethod(anyString(), anyString(), anyString(), Mockito.isNotNull())) when(daprClient.invokeActorMethod(anyString(), anyString(), anyString(), Mockito.isNotNull()))
@ -355,7 +356,7 @@ public class ActorProxyImplTest {
} }
@Test(expected = RuntimeException.class) @Test(expected = DaprException.class)
public void invokeActorMethodSavingDataWithIncorrectInputType() { public void invokeActorMethodSavingDataWithIncorrectInputType() {
final DaprClient daprClient = mock(DaprClient.class); final DaprClient daprClient = mock(DaprClient.class);
when(daprClient.invokeActorMethod(anyString(), anyString(), anyString(), Mockito.isNotNull())) when(daprClient.invokeActorMethod(anyString(), anyString(), anyString(), Mockito.isNotNull()))
@ -402,7 +403,7 @@ public class ActorProxyImplTest {
} }
@Test(expected = RuntimeException.class) @Test(expected = DaprException.class)
public void invokeActorMethodWithDataWithVoidIncorrectInputType() { public void invokeActorMethodWithDataWithVoidIncorrectInputType() {
MyData saveData = new MyData(); MyData saveData = new MyData();
saveData.setPropertyA("valueA"); saveData.setPropertyA("valueA");

View File

@ -14,6 +14,9 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.concurrent.ExecutionException;
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -89,8 +92,12 @@ public class DaprGrpcClientTest {
return true; return true;
}))).thenReturn(settableFuture); }))).thenReturn(settableFuture);
Mono<byte[]> result = client.invokeActorMethod(ACTOR_TYPE, ACTOR_ID, methodName, null); Mono<byte[]> result = client.invokeActorMethod(ACTOR_TYPE, ACTOR_ID, methodName, null);
Exception exception = assertThrows(Exception.class, () -> result.block());
assertTrue(exception.getCause().getCause() instanceof ArithmeticException); assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.ArithmeticException",
() -> result.block());
} }
@Test @Test

View File

@ -8,14 +8,16 @@ import io.dapr.client.DaprHttp;
import io.dapr.client.DaprHttpProxy; import io.dapr.client.DaprHttpProxy;
import io.dapr.config.Properties; import io.dapr.config.Properties;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.mock.Behavior; import okhttp3.mock.Behavior;
import okhttp3.mock.MediaTypes;
import okhttp3.mock.MockInterceptor; import okhttp3.mock.MockInterceptor;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
public class DaprHttpClientTest { public class DaprHttpClientTest {
@ -35,15 +37,33 @@ public class DaprHttpClientTest {
@Test @Test
public void invokeActorMethod() { public void invokeActorMethod() {
DaprHttp daprHttpMock = mock(DaprHttp.class);
mockInterceptor.addRule() mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/actors/DemoActor/1/method/Payment") .post("http://127.0.0.1:3000/v1.0/actors/DemoActor/1/method/Payment")
.respond(EXPECTED_RESULT); .respond(EXPECTED_RESULT);
DaprHttp daprHttp = new DaprHttpProxy(Properties.SIDECAR_IP.get(), 3000, okHttpClient); DaprHttp daprHttp = new DaprHttpProxy(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
DaprHttpClient = new DaprHttpClient(daprHttp); DaprHttpClient = new DaprHttpClient(daprHttp);
Mono<byte[]> mono = Mono<byte[]> mono =
DaprHttpClient.invokeActorMethod("DemoActor", "1", "Payment", "".getBytes()); DaprHttpClient.invokeActorMethod("DemoActor", "1", "Payment", "".getBytes());
assertEquals(new String(mono.block()), EXPECTED_RESULT); assertEquals(new String(mono.block()), EXPECTED_RESULT);
} }
@Test
public void invokeActorMethodError() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/actors/DemoActor/1/method/Payment")
.respond(404,
ResponseBody.create("" +
"{\"errorCode\":\"ERR_SOMETHING\"," +
"\"message\":\"error message\"}", MediaTypes.MEDIATYPE_JSON));
DaprHttp daprHttp = new DaprHttpProxy(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
DaprHttpClient = new DaprHttpClient(daprHttp);
Mono<byte[]> mono =
DaprHttpClient.invokeActorMethod("DemoActor", "1", "Payment", "".getBytes());
assertThrowsDaprException(
"ERR_SOMETHING",
"ERR_SOMETHING: error message",
() -> mono.block());
}
} }

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
package io.dapr.it;
import io.dapr.exceptions.DaprException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
public final class TestUtils {
private TestUtils() {}
public static <T extends Throwable> void assertThrowsDaprException(Class<T> expectedType, Executable executable) {
Throwable cause = Assertions.assertThrows(DaprException.class, executable).getCause();
Assertions.assertNotNull(cause);
Assertions.assertEquals(expectedType, cause.getClass());
}
public static void assertThrowsDaprException(String expectedErrorCode, Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNull(daprException.getCause());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
}
public static <T extends Throwable> void assertThrowsDaprException(
String expectedErrorCode,
String expectedErrorMessage,
Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
}
}

View File

@ -66,7 +66,7 @@ public class MethodInvokeIT extends BaseIT {
} }
@Test @Test
public void testInvoke() throws IOException { public void testInvoke() throws Exception {
// At this point, it is guaranteed that the service above is running and all ports being listened to. // At this point, it is guaranteed that the service above is running and all ports being listened to.
@ -94,7 +94,7 @@ public class MethodInvokeIT extends BaseIT {
} }
@Test @Test
public void testInvokeWithObjects() throws IOException { public void testInvokeWithObjects() throws Exception {
try (DaprClient client = new DaprClientBuilder().build()) { try (DaprClient client = new DaprClientBuilder().build()) {
for (int i = 0; i < NUM_MESSAGES; i++) { for (int i = 0; i < NUM_MESSAGES; i++) {
Person person = new Person(); Person person = new Person();

View File

@ -96,7 +96,7 @@ public class SecretsClientIT extends BaseIT {
} }
@After @After
public void tearDown() throws IOException { public void tearDown() throws Exception {
daprClient.close(); daprClient.close();
} }

View File

@ -18,9 +18,12 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import static io.dapr.it.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
/** /**
* Common test cases for Dapr client (GRPC and HTTP). * Common test cases for Dapr client (GRPC and HTTP).
@ -60,6 +63,22 @@ public abstract class AbstractStateClientIT extends BaseIT {
Assert.assertEquals("data in property B", myDataResponse.getValue().getPropertyB()); Assert.assertEquals("data in property B", myDataResponse.getValue().getPropertyB());
} }
@Test
public void getStateKeyNotFound() {
final String stateKey = "unknownKey";
DaprClient daprClient = buildDaprClient();
State<String> state = (State<String>)
daprClient.getState(STATE_STORE_NAME, new State(stateKey), String.class).block();
Assert.assertNotNull(state);
Assert.assertEquals("unknownKey", state.getKey());
Assert.assertNull(state.getValue());
// gRPC returns empty eTag while HTTP returns null.
// TODO(artursouza): https://github.com/dapr/java-sdk/issues/405
Assert.assertTrue(state.getEtag() == null || state.getEtag().isEmpty());
}
@Test @Test
public void saveAndGetBulkStates() { public void saveAndGetBulkStates() {
final String stateKeyOne = UUID.randomUUID().toString(); final String stateKeyOne = UUID.randomUUID().toString();

View File

@ -8,12 +8,16 @@ package io.dapr.it.state;
import io.dapr.client.DaprClient; import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprClientGrpc; import io.dapr.client.DaprClientGrpc;
import io.dapr.client.domain.State;
import io.dapr.it.DaprRun; import io.dapr.it.DaprRun;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import static io.dapr.it.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
@ -35,7 +39,7 @@ public class GRPCStateClientIT extends AbstractStateClientIT {
} }
@AfterClass @AfterClass
public static void tearDown() throws IOException { public static void tearDown() throws Exception {
daprClient.close(); daprClient.close();
} }
@ -44,7 +48,45 @@ public class GRPCStateClientIT extends AbstractStateClientIT {
return daprClient; return daprClient;
} }
/** Tests where HTTP and GRPC behavior differ in Dapr runtime. **/
@Test
public void getStateStoreNotFound() {
final String stateKey = "key";
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"INVALID_ARGUMENT",
"INVALID_ARGUMENT: state store unknown state store is not found",
() -> daprClient.getState("unknown state store", new State(stateKey), byte[].class).block());
}
@Test
public void getStatesStoreNotFound() {
final String stateKey = "key";
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"INVALID_ARGUMENT",
"INVALID_ARGUMENT: state store unknown state store is not found",
() -> daprClient.getStates(
"unknown state store",
Collections.singletonList(stateKey),
byte[].class).block());
}
@Test
public void publishPubSubNotFound() {
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"NOT_FOUND",
"NOT_FOUND: pubsub 'unknown pubsub' not found",
() -> daprClient.publishEvent("unknown pubsub", "mytopic", "payload").block());
}
} }

View File

@ -8,12 +8,16 @@ package io.dapr.it.state;
import io.dapr.client.DaprClient; import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprClientHttp; import io.dapr.client.DaprClientHttp;
import io.dapr.client.domain.State;
import io.dapr.it.DaprRun; import io.dapr.it.DaprRun;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import static io.dapr.it.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
@ -34,7 +38,7 @@ public class HttpStateClientIT extends AbstractStateClientIT {
} }
@AfterClass @AfterClass
public static void tearDown() throws IOException { public static void tearDown() throws Exception {
daprClient.close(); daprClient.close();
} }
@ -43,4 +47,45 @@ public class HttpStateClientIT extends AbstractStateClientIT {
return daprClient; return daprClient;
} }
/** Tests where HTTP and GRPC behavior differ in Dapr runtime. **/
@Test
public void getStateStoreNotFound() {
final String stateKey = "key";
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"ERR_STATE_STORE_NOT_FOUND",
"ERR_STATE_STORE_NOT_FOUND: state store unknown%20state%20store is not found",
() -> daprClient.getState("unknown state store", new State(stateKey), byte[].class).block());
}
@Test
public void getStatesStoreNotFound() {
final String stateKey = "key";
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"ERR_STATE_STORE_NOT_FOUND",
"ERR_STATE_STORE_NOT_FOUND: state store unknown%20state%20store is not found",
() -> daprClient.getStates(
"unknown state store",
Collections.singletonList(stateKey),
byte[].class).block());
}
@Test
public void publishPubSubNotFound() {
DaprClient daprClient = buildDaprClient();
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
assertThrowsDaprException(
"ERR_PUBSUB_NOT_FOUND",
"ERR_PUBSUB_NOT_FOUND: pubsub 'unknown%20pubsub' not found",
() -> daprClient.publishEvent("unknown pubsub", "mytopic", "payload").block());
}
} }

View File

@ -31,7 +31,7 @@ import java.util.Map;
* *
* @see io.dapr.client.DaprClientBuilder for information on how to make instance for this interface. * @see io.dapr.client.DaprClientBuilder for information on how to make instance for this interface.
*/ */
public interface DaprClient extends Closeable { public interface DaprClient extends AutoCloseable {
/** /**
* Publish an event. * Publish an event.

View File

@ -14,6 +14,8 @@ import io.grpc.ManagedChannelBuilder;
import java.io.Closeable; import java.io.Closeable;
import static io.dapr.exceptions.DaprException.throwIllegalArgumentException;
/** /**
* A builder for the DaprClient, * A builder for the DaprClient,
* Currently only and HTTP Client will be supported. * Currently only and HTTP Client will be supported.
@ -63,11 +65,11 @@ public class DaprClientBuilder {
*/ */
public DaprClientBuilder withObjectSerializer(DaprObjectSerializer objectSerializer) { public DaprClientBuilder withObjectSerializer(DaprObjectSerializer objectSerializer) {
if (objectSerializer == null) { if (objectSerializer == null) {
throw new IllegalArgumentException("Object serializer is required"); throwIllegalArgumentException("Object serializer is required");
} }
if (objectSerializer.getContentType() == null || objectSerializer.getContentType().isEmpty()) { if (objectSerializer.getContentType() == null || objectSerializer.getContentType().isEmpty()) {
throw new IllegalArgumentException("Content Type should not be null or empty"); throwIllegalArgumentException("Content Type should not be null or empty");
} }
this.objectSerializer = objectSerializer; this.objectSerializer = objectSerializer;
@ -83,7 +85,7 @@ public class DaprClientBuilder {
*/ */
public DaprClientBuilder withStateSerializer(DaprObjectSerializer stateSerializer) { public DaprClientBuilder withStateSerializer(DaprObjectSerializer stateSerializer) {
if (stateSerializer == null) { if (stateSerializer == null) {
throw new IllegalArgumentException("State serializer is required"); throwIllegalArgumentException("State serializer is required");
} }
this.stateSerializer = stateSerializer; this.stateSerializer = stateSerializer;
@ -113,7 +115,7 @@ public class DaprClientBuilder {
private DaprClient buildDaprClientGrpc() { private DaprClient buildDaprClientGrpc() {
int port = Properties.GRPC_PORT.get(); int port = Properties.GRPC_PORT.get();
if (port <= 0) { if (port <= 0) {
throw new IllegalStateException("Invalid port."); throwIllegalArgumentException("Invalid port.");
} }
ManagedChannel channel = ManagedChannelBuilder.forAddress( ManagedChannel channel = ManagedChannelBuilder.forAddress(
Properties.SIDECAR_IP.get(), port).usePlaintext().build(); Properties.SIDECAR_IP.get(), port).usePlaintext().build();

View File

@ -9,7 +9,6 @@ import com.google.common.base.Strings;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.Any; import com.google.protobuf.Any;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import io.dapr.client.domain.DeleteStateRequest; import io.dapr.client.domain.DeleteStateRequest;
import io.dapr.client.domain.ExecuteStateTransactionRequest; import io.dapr.client.domain.ExecuteStateTransactionRequest;
import io.dapr.client.domain.GetSecretRequest; import io.dapr.client.domain.GetSecretRequest;
@ -25,6 +24,7 @@ import io.dapr.client.domain.State;
import io.dapr.client.domain.StateOptions; import io.dapr.client.domain.StateOptions;
import io.dapr.client.domain.TransactionalStateOperation; import io.dapr.client.domain.TransactionalStateOperation;
import io.dapr.config.Properties; import io.dapr.config.Properties;
import io.dapr.exceptions.DaprException;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.utils.TypeRef; import io.dapr.utils.TypeRef;
import io.dapr.v1.CommonProtos; import io.dapr.v1.CommonProtos;
@ -149,12 +149,11 @@ public class DaprClientGrpc extends AbstractDaprClient {
.setData(ByteString.copyFrom(objectSerializer.serialize(data))).build(); .setData(ByteString.copyFrom(objectSerializer.serialize(data))).build();
return Mono.fromCallable(wrap(context, () -> { return Mono.fromCallable(wrap(context, () -> {
ListenableFuture<Empty> futureEmpty = client.publishEvent(envelope); get(client.publishEvent(envelope));
futureEmpty.get();
return null; return null;
})); }));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -178,10 +177,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
ListenableFuture<CommonProtos.InvokeResponse> futureResponse = ListenableFuture<CommonProtos.InvokeResponse> futureResponse =
client.invokeService(envelope); client.invokeService(envelope);
return objectSerializer.deserialize(futureResponse.get().getData().getValue().toByteArray(), type); return objectSerializer.deserialize(get(futureResponse).getData().getValue().toByteArray(), type);
})).map(r -> new Response<>(context, r)); })).map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -216,10 +215,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
DaprProtos.InvokeBindingRequest envelope = builder.build(); DaprProtos.InvokeBindingRequest envelope = builder.build();
return Mono.fromCallable(wrap(context, () -> { return Mono.fromCallable(wrap(context, () -> {
ListenableFuture<DaprProtos.InvokeBindingResponse> futureResponse = client.invokeBinding(envelope); ListenableFuture<DaprProtos.InvokeBindingResponse> futureResponse = client.invokeBinding(envelope);
return objectSerializer.deserialize(futureResponse.get().getData().toByteArray(), type); return objectSerializer.deserialize(get(futureResponse).getData().toByteArray(), type);
})).map(r -> new Response<>(context, r)); })).map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -253,16 +252,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
DaprProtos.GetStateRequest envelope = builder.build(); DaprProtos.GetStateRequest envelope = builder.build();
return Mono.fromCallable(wrap(context, () -> { return Mono.fromCallable(wrap(context, () -> {
ListenableFuture<DaprProtos.GetStateResponse> futureResponse = client.getState(envelope); ListenableFuture<DaprProtos.GetStateResponse> futureResponse = client.getState(envelope);
DaprProtos.GetStateResponse response = null; return buildStateKeyValue(get(futureResponse), key, options, type);
try {
response = futureResponse.get();
} catch (NullPointerException npe) {
return null;
}
return buildStateKeyValue(response, key, options, type);
})).map(s -> new Response<>(context, s)); })).map(s -> new Response<>(context, s));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -294,12 +287,7 @@ public class DaprClientGrpc extends AbstractDaprClient {
DaprProtos.GetBulkStateRequest envelope = builder.build(); DaprProtos.GetBulkStateRequest envelope = builder.build();
return Mono.fromCallable(wrap(context, () -> { return Mono.fromCallable(wrap(context, () -> {
ListenableFuture<DaprProtos.GetBulkStateResponse> futureResponse = client.getBulkState(envelope); ListenableFuture<DaprProtos.GetBulkStateResponse> futureResponse = client.getBulkState(envelope);
DaprProtos.GetBulkStateResponse response = null; DaprProtos.GetBulkStateResponse response = get(futureResponse);
try {
response = futureResponse.get();
} catch (NullPointerException npe) {
return null;
}
return response return response
.getItemsList() .getItemsList()
@ -307,14 +295,15 @@ public class DaprClientGrpc extends AbstractDaprClient {
.map(b -> { .map(b -> {
try { try {
return buildStateKeyValue(b, type); return buildStateKeyValue(b, type);
} catch (IOException e) { } catch (Exception e) {
throw new RuntimeException(e); DaprException.wrap(e);
return null;
} }
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
})).map(s -> new Response<>(context, s)); })).map(s -> new Response<>(context, s));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -374,16 +363,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
} }
DaprProtos.ExecuteStateTransactionRequest req = builder.build(); DaprProtos.ExecuteStateTransactionRequest req = builder.build();
return Mono.fromCallable(wrap(context, () -> client.executeStateTransaction(req))).flatMap(f -> { return Mono.fromCallable(wrap(context, () -> client.executeStateTransaction(req))).map(f -> get(f))
try { .thenReturn(new Response<>(context, null));
f.get(); } catch (Exception e) {
} catch (Exception e) { return DaprException.wrapMono(e);
return Mono.error(e);
}
return Mono.empty();
}).thenReturn(new Response<>(context, null));
} catch (IOException e) {
return Mono.error(e);
} }
} }
@ -406,16 +389,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
} }
DaprProtos.SaveStateRequest req = builder.build(); DaprProtos.SaveStateRequest req = builder.build();
return Mono.fromCallable(wrap(context, () -> client.saveState(req))).flatMap(f -> { return Mono.fromCallable(wrap(context, () -> client.saveState(req))).map(f -> get(f))
try { .thenReturn(new Response<>(context, null));
f.get();
} catch (Exception ex) {
return Mono.error(ex);
}
return Mono.empty();
}).thenReturn(new Response<>(context, null));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -492,16 +469,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
} }
DaprProtos.DeleteStateRequest req = builder.build(); DaprProtos.DeleteStateRequest req = builder.build();
return Mono.fromCallable(wrap(context, () -> client.deleteState(req))).flatMap(f -> { return Mono.fromCallable(wrap(context, () -> client.deleteState(req))).map(f -> get(f))
try { .thenReturn(new Response<>(context, null));
f.get();
} catch (Exception ex) {
return Mono.error(ex);
}
return Mono.empty();
}).thenReturn(new Response<>(context, null));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -563,7 +534,7 @@ public class DaprClientGrpc extends AbstractDaprClient {
throw new IllegalArgumentException("Secret key cannot be null or empty."); throw new IllegalArgumentException("Secret key cannot be null or empty.");
} }
} catch (Exception e) { } catch (Exception e) {
return Mono.error(e); return DaprException.wrapMono(e);
} }
DaprProtos.GetSecretRequest.Builder requestBuilder = DaprProtos.GetSecretRequest.newBuilder() DaprProtos.GetSecretRequest.Builder requestBuilder = DaprProtos.GetSecretRequest.newBuilder()
@ -576,7 +547,7 @@ public class DaprClientGrpc extends AbstractDaprClient {
return Mono.fromCallable(wrap(context, () -> { return Mono.fromCallable(wrap(context, () -> {
DaprProtos.GetSecretRequest req = requestBuilder.build(); DaprProtos.GetSecretRequest req = requestBuilder.build();
ListenableFuture<DaprProtos.GetSecretResponse> future = client.getSecret(req); ListenableFuture<DaprProtos.GetSecretResponse> future = client.getSecret(req);
return future.get(); return get(future);
})).map(future -> new Response<>(context, future.getDataMap())); })).map(future -> new Response<>(context, future.getDataMap()));
} }
@ -586,9 +557,12 @@ public class DaprClientGrpc extends AbstractDaprClient {
* @throws IOException on exception. * @throws IOException on exception.
*/ */
@Override @Override
public void close() throws IOException { public void close() throws Exception {
if (channel != null) { if (channel != null) {
channel.close(); DaprException.wrap(() -> {
channel.close();
return true;
}).call();
} }
} }
@ -658,15 +632,25 @@ public class DaprClientGrpc extends AbstractDaprClient {
} }
}); });
} catch (SpanContextParseException e) { } catch (SpanContextParseException e) {
throw new RuntimeException(e); throw new DaprException(e);
} }
} }
private static <V> Callable<V> wrap(Context context, Callable<V> callable) { private static <V> Callable<V> wrap(Context context, Callable<V> callable) {
if (context == null) { if (context == null) {
return callable; return DaprException.wrap(callable);
} }
return context.wrap(callable); return DaprException.wrap(context.wrap(callable));
}
private static <V> V get(ListenableFuture<V> future) {
try {
return future.get();
} catch (Exception e) {
DaprException.wrap(e);
}
return null;
} }
} }

View File

@ -23,6 +23,7 @@ import io.dapr.client.domain.StateOptions;
import io.dapr.client.domain.TransactionalStateOperation; import io.dapr.client.domain.TransactionalStateOperation;
import io.dapr.client.domain.TransactionalStateRequest; import io.dapr.client.domain.TransactionalStateRequest;
import io.dapr.config.Properties; import io.dapr.config.Properties;
import io.dapr.exceptions.DaprException;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.serializer.DefaultObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer;
import io.dapr.utils.TypeRef; import io.dapr.utils.TypeRef;
@ -159,7 +160,7 @@ public class DaprClientHttp extends AbstractDaprClient {
DaprHttp.HttpMethods.POST.name(), url.toString(), null, serializedEvent, metadata, context) DaprHttp.HttpMethods.POST.name(), url.toString(), null, serializedEvent, metadata, context)
.thenReturn(new Response<>(context, null)); .thenReturn(new Response<>(context, null));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -198,11 +199,11 @@ public class DaprClientHttp extends AbstractDaprClient {
return Mono.just(object); return Mono.just(object);
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
}).map(r -> new Response<>(context, r)); }).map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -266,11 +267,11 @@ public class DaprClientHttp extends AbstractDaprClient {
return Mono.just(object); return Mono.just(object);
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
}).map(r -> new Response<>(context, r)); }).map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -307,13 +308,13 @@ public class DaprClientHttp extends AbstractDaprClient {
try { try {
return Mono.just(buildStates(s, type)); return Mono.just(buildStates(s, type));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
}) })
.map(r -> new Response<>(context, r)); .map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -358,12 +359,12 @@ public class DaprClientHttp extends AbstractDaprClient {
try { try {
return Mono.just(buildState(s, key, options, type)); return Mono.just(buildState(s, key, options, type));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
}) })
.map(r -> new Response<>(context, r)); .map(r -> new Response<>(context, r));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -383,19 +384,12 @@ public class DaprClientHttp extends AbstractDaprClient {
if (operations == null || operations.isEmpty()) { if (operations == null || operations.isEmpty()) {
return Mono.empty(); return Mono.empty();
} }
final Map<String, String> headers = new HashMap<>();
final String etag = operations.stream()
.filter(op -> null != op.getRequest().getEtag() && !op.getRequest().getEtag().trim().isEmpty())
.findFirst()
.orElse(new TransactionalStateOperation<>(null, new State<>(null,null, null, null)))
.getRequest()
.getEtag();
if (etag != null && !etag.trim().isEmpty()) {
headers.put(HEADER_HTTP_ETAG_ID, etag);
}
final String url = String.format(TRANSACTION_URL_FORMAT, stateStoreName); final String url = String.format(TRANSACTION_URL_FORMAT, stateStoreName);
List<TransactionalStateOperation<Object>> internalOperationObjects = new ArrayList<>(operations.size()); List<TransactionalStateOperation<Object>> internalOperationObjects = new ArrayList<>(operations.size());
for (TransactionalStateOperation operation : operations) { for (TransactionalStateOperation operation : operations) {
if (operation == null) {
continue;
}
State<?> state = operation.getRequest(); State<?> state = operation.getRequest();
if (state == null) { if (state == null) {
continue; continue;
@ -416,10 +410,10 @@ public class DaprClientHttp extends AbstractDaprClient {
TransactionalStateRequest<Object> req = new TransactionalStateRequest<>(internalOperationObjects, metadata); TransactionalStateRequest<Object> req = new TransactionalStateRequest<>(internalOperationObjects, metadata);
byte[] serializedOperationBody = INTERNAL_SERIALIZER.serialize(req); byte[] serializedOperationBody = INTERNAL_SERIALIZER.serialize(req);
return this.client.invokeApi( return this.client.invokeApi(
DaprHttp.HttpMethods.POST.name(), url, null, serializedOperationBody, headers, context) DaprHttp.HttpMethods.POST.name(), url, null, serializedOperationBody, null, context)
.thenReturn(new Response<>(context, null)); .thenReturn(new Response<>(context, null));
} catch (IOException e) { } catch (Exception e) {
return Mono.error(e); return DaprException.wrapMono(e);
} }
} }
@ -438,12 +432,6 @@ public class DaprClientHttp extends AbstractDaprClient {
if (states == null || states.isEmpty()) { if (states == null || states.isEmpty()) {
return Mono.empty(); return Mono.empty();
} }
final Map<String, String> headers = new HashMap<>();
final String etag = states.stream().filter(state -> null != state.getEtag() && !state.getEtag().trim().isEmpty())
.findFirst().orElse(new State<>(null, null, null, null)).getEtag();
if (etag != null && !etag.trim().isEmpty()) {
headers.put(HEADER_HTTP_ETAG_ID, etag);
}
final String url = STATE_PATH + "/" + stateStoreName; final String url = STATE_PATH + "/" + stateStoreName;
List<State<Object>> internalStateObjects = new ArrayList<>(states.size()); List<State<Object>> internalStateObjects = new ArrayList<>(states.size());
for (State state : states) { for (State state : states) {
@ -466,10 +454,10 @@ public class DaprClientHttp extends AbstractDaprClient {
} }
byte[] serializedStateBody = INTERNAL_SERIALIZER.serialize(internalStateObjects); byte[] serializedStateBody = INTERNAL_SERIALIZER.serialize(internalStateObjects);
return this.client.invokeApi( return this.client.invokeApi(
DaprHttp.HttpMethods.POST.name(), url, null, serializedStateBody, headers, context) DaprHttp.HttpMethods.POST.name(), url, null, serializedStateBody, null, context)
.thenReturn(new Response<>(context, null)); .thenReturn(new Response<>(context, null));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -506,7 +494,7 @@ public class DaprClientHttp extends AbstractDaprClient {
DaprHttp.HttpMethods.DELETE.name(), url, urlParameters, headers, context) DaprHttp.HttpMethods.DELETE.name(), url, urlParameters, headers, context)
.thenReturn(new Response<>(context, null)); .thenReturn(new Response<>(context, null));
} catch (Exception ex) { } catch (Exception ex) {
return Mono.error(ex); return DaprException.wrapMono(ex);
} }
} }
@ -581,7 +569,7 @@ public class DaprClientHttp extends AbstractDaprClient {
throw new IllegalArgumentException("Secret key cannot be null or empty."); throw new IllegalArgumentException("Secret key cannot be null or empty.");
} }
} catch (Exception e) { } catch (Exception e) {
return Mono.error(e); return DaprException.wrapMono(e);
} }
String url = SECRETS_PATH + "/" + secretStoreName + "/" + key; String url = SECRETS_PATH + "/" + secretStoreName + "/" + key;
@ -596,7 +584,7 @@ public class DaprClientHttp extends AbstractDaprClient {
return Mono.just(m); return Mono.just(m);
} catch (IOException e) { } catch (IOException e) {
return Mono.error(e); return DaprException.wrapMono(e);
} }
}) })
.map(m -> (Map<String, String>)m) .map(m -> (Map<String, String>)m)
@ -604,7 +592,11 @@ public class DaprClientHttp extends AbstractDaprClient {
} }
@Override @Override
public void close() throws IOException { public void close() {
client.close(); try {
client.close();
} catch (Exception e) {
DaprException.wrap(e);
}
} }
} }

View File

@ -12,7 +12,6 @@ import io.dapr.exceptions.DaprException;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.propagation.HttpTraceContext; import io.opentelemetry.api.trace.propagation.HttpTraceContext;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapPropagator;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@ -22,7 +21,6 @@ import okhttp3.ResponseBody;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
@ -32,7 +30,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class DaprHttp implements Closeable { public class DaprHttp implements AutoCloseable {
/** /**
* Dapr API used in this client. * Dapr API used in this client.
@ -221,7 +219,7 @@ public class DaprHttp implements Closeable {
* @see OkHttpClient * @see OkHttpClient
*/ */
@Override @Override
public void close() throws IOException { public void close() {
// No code needed // No code needed
} }
@ -297,7 +295,7 @@ public class DaprHttp implements Closeable {
throw new DaprException(error); throw new DaprException(error);
} }
throw new IllegalStateException("Unknown Dapr error. HTTP status code: " + response.code()); throw new DaprException("UNKNOWN", "HTTP status code: " + response.code());
} }
Map<String, String> mapHeaders = new HashMap<>(); Map<String, String> mapHeaders = new HashMap<>();

View File

@ -26,12 +26,12 @@ public class GetStatesRequestBuilder {
public GetStatesRequestBuilder(String stateStoreName, List<String> keys) { public GetStatesRequestBuilder(String stateStoreName, List<String> keys) {
this.stateStoreName = stateStoreName; this.stateStoreName = stateStoreName;
this.keys = Collections.unmodifiableList(keys); this.keys = keys == null ? null : Collections.unmodifiableList(keys);
} }
public GetStatesRequestBuilder(String stateStoreName, String... keys) { public GetStatesRequestBuilder(String stateStoreName, String... keys) {
this.stateStoreName = stateStoreName; this.stateStoreName = stateStoreName;
this.keys = Collections.unmodifiableList(Arrays.asList(keys)); this.keys = keys == null ? null : Collections.unmodifiableList(Arrays.asList(keys));
} }
public GetStatesRequestBuilder withParallelism(int parallelism) { public GetStatesRequestBuilder withParallelism(int parallelism) {

View File

@ -6,6 +6,7 @@
package io.dapr.client.domain; package io.dapr.client.domain;
import io.dapr.client.DaprHttp; import io.dapr.client.DaprHttp;
import io.dapr.exceptions.DaprException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -73,13 +74,18 @@ public final class HttpExtension {
* @throws IllegalArgumentException on null method or queryString. * @throws IllegalArgumentException on null method or queryString.
*/ */
public HttpExtension(DaprHttp.HttpMethods method, Map<String, String> queryString) { public HttpExtension(DaprHttp.HttpMethods method, Map<String, String> queryString) {
if (method == null) { try {
throw new IllegalArgumentException("HttpExtension method cannot be null"); if (method == null) {
} else if (queryString == null) { throw new IllegalArgumentException("HttpExtension method cannot be null");
throw new IllegalArgumentException("HttpExtension queryString map cannot be null"); } else if (queryString == null) {
throw new IllegalArgumentException("HttpExtension queryString map cannot be null");
}
this.method = method;
this.queryString = Collections.unmodifiableMap(queryString);
} catch (RuntimeException e) {
DaprException.wrap(e);
} }
this.method = method;
this.queryString = Collections.unmodifiableMap(queryString);
} }
public DaprHttp.HttpMethods getMethod() { public DaprHttp.HttpMethods getMethod() {

View File

@ -5,6 +5,13 @@
package io.dapr.exceptions; package io.dapr.exceptions;
import io.grpc.StatusRuntimeException;
import reactor.core.publisher.Mono;
import java.lang.reflect.Executable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
/** /**
* A Dapr's specific exception. * A Dapr's specific exception.
*/ */
@ -32,10 +39,18 @@ public class DaprException extends RuntimeException {
* permitted, and indicates that the cause is nonexistent or * permitted, and indicates that the cause is nonexistent or
* unknown.) * unknown.)
*/ */
public DaprException(DaprError daprError, Throwable cause) { public DaprException(DaprError daprError, Exception cause) {
this(daprError.getErrorCode(), daprError.getMessage(), cause); this(daprError.getErrorCode(), daprError.getMessage(), cause);
} }
/**
* Wraps an exception into a DaprException.
* @param exception the exception to be wrapped.
*/
public DaprException(Exception exception) {
this("UNKNOWN", exception.getMessage(), exception);
}
/** /**
* New Exception from a client-side generated error code and message. * New Exception from a client-side generated error code and message.
* *
@ -56,8 +71,8 @@ public class DaprException extends RuntimeException {
* permitted, and indicates that the cause is nonexistent or * permitted, and indicates that the cause is nonexistent or
* unknown.) * unknown.)
*/ */
public DaprException(String errorCode, String message, Throwable cause) { public DaprException(String errorCode, String message, Exception cause) {
super(String.format("%s: %s", errorCode, message), cause); super(String.format("%s: %s", errorCode, emptyIfNull(message)), cause);
this.errorCode = errorCode; this.errorCode = errorCode;
} }
@ -69,4 +84,88 @@ public class DaprException extends RuntimeException {
public String getErrorCode() { public String getErrorCode() {
return this.errorCode; return this.errorCode;
} }
/**
* Convenience to throw an wrapped IllegalArgumentException.
* @param message Message for exception.
*/
public static void throwIllegalArgumentException(String message) {
try {
throw new IllegalArgumentException(message);
} catch (Exception e) {
wrap(e);
}
}
/**
* Wraps an exception into DaprException (if not already DaprException).
*
* @param exception Exception to be wrapped.
* @return DaprException.
*/
public static DaprException wrap(Exception exception) {
if (exception == null) {
return null;
}
if (exception instanceof DaprException) {
throw (DaprException) exception;
}
Throwable e = exception;
while (e != null) {
if (e instanceof StatusRuntimeException) {
StatusRuntimeException statusRuntimeException = (StatusRuntimeException) e;
throw new DaprException(
statusRuntimeException.getStatus().getCode().toString(),
statusRuntimeException.getStatus().getDescription(),
exception);
}
e = e.getCause();
}
throw new DaprException(exception);
}
/**
* Wraps a callable with a try-catch to throw DaprException.
* @param callable callable to be invoked.
* @param <T> type to be returned
* @return object of type T.
*/
public static <T> Callable<T> wrap(Callable<T> callable) {
return () -> {
try {
return callable.call();
} catch (Exception e) {
return (T) wrap(e);
}
};
}
/**
* Wraps an exception into DaprException (if not already DaprException).
*
* @param exception Exception to be wrapped.
* @param <T> Mono's response type.
* @return Mono containing DaprException.
*/
public static <T> Mono<T> wrapMono(Exception exception) {
try {
wrap(exception);
} catch (Exception e) {
return Mono.error(e);
}
return Mono.empty();
}
private static String emptyIfNull(String str) {
if (str == null) {
return "";
}
return str;
}
} }

View File

@ -5,6 +5,7 @@
package io.dapr.client; package io.dapr.client;
import io.dapr.exceptions.DaprException;
import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DaprObjectSerializer;
import org.junit.Test; import org.junit.Test;
@ -26,17 +27,17 @@ public class DaprClientBuilderTest {
assertNotNull(daprClient); assertNotNull(daprClient);
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void noObjectSerializer() { public void noObjectSerializer() {
new DaprClientBuilder().withObjectSerializer(null); new DaprClientBuilder().withObjectSerializer(null);
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void blankContentTypeInObjectSerializer() { public void blankContentTypeInObjectSerializer() {
new DaprClientBuilder().withObjectSerializer(mock(DaprObjectSerializer.class)); new DaprClientBuilder().withObjectSerializer(mock(DaprObjectSerializer.class));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = DaprException.class)
public void noStateSerializer() { public void noStateSerializer() {
new DaprClientBuilder().withStateSerializer(null); new DaprClientBuilder().withStateSerializer(null);
} }

View File

@ -29,6 +29,9 @@ import io.dapr.utils.TypeRef;
import io.dapr.v1.CommonProtos; import io.dapr.v1.CommonProtos;
import io.dapr.v1.DaprGrpc; import io.dapr.v1.DaprGrpc;
import io.dapr.v1.DaprProtos; import io.dapr.v1.DaprProtos;
import io.grpc.Status;
import io.grpc.StatusException;
import io.grpc.StatusRuntimeException;
import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -44,9 +47,11 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import static com.google.common.util.concurrent.Futures.addCallback; import static com.google.common.util.concurrent.Futures.addCallback;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static io.dapr.utils.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -85,34 +90,43 @@ public class DaprClientGrpcTest {
} }
@After @After
public void tearDown() throws IOException { public void tearDown() throws Exception {
adapter.close(); adapter.close();
verify(closeable).close(); verify(closeable).close();
verifyNoMoreInteractions(closeable); verifyNoMoreInteractions(closeable);
} }
@Test(expected = RuntimeException.class) @Test
public void publishEventExceptionThrownTest() { public void publishEventExceptionThrownTest() {
when(client.publishEvent(any(DaprProtos.PublishEventRequest.class))) when(client.publishEvent(any(DaprProtos.PublishEventRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(newStatusRuntimeException("INVALID_ARGUMENT", "bad bad argument"));
Mono<Void> result = adapter.publishEvent("pubsubname","topic", "object");
result.block(); assertThrowsDaprException(
StatusRuntimeException.class,
"INVALID_ARGUMENT",
"INVALID_ARGUMENT: bad bad argument",
() -> adapter.publishEvent("pubsubname","topic", "object").block());
} }
@Test(expected = RuntimeException.class) @Test
public void publishEventCallbackExceptionThrownTest() { public void publishEventCallbackExceptionThrownTest() {
SettableFuture<Empty> settableFuture = SettableFuture.create(); SettableFuture<Empty> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = newStatusRuntimeException("INVALID_ARGUMENT", "bad bad argument");
MockCallback<Empty> callback = new MockCallback<>(ex); MockCallback<Empty> callback = new MockCallback<>(ex);
addCallback(settableFuture, callback, directExecutor()); addCallback(settableFuture, callback, directExecutor());
when(client.publishEvent(any(DaprProtos.PublishEventRequest.class))) when(client.publishEvent(any(DaprProtos.PublishEventRequest.class)))
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<Void> result = adapter.publishEvent("pubsubname","topic", "object"); Mono<Void> result = adapter.publishEvent("pubsubname","topic", "object");
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"INVALID_ARGUMENT",
"INVALID_ARGUMENT: bad bad argument",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void publishEventSerializeException() throws IOException { public void publishEventSerializeException() throws IOException {
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class); DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
adapter = new DaprClientGrpc(closeable, client, mockSerializer, new DefaultObjectSerializer()); adapter = new DaprClientGrpc(closeable, client, mockSerializer, new DefaultObjectSerializer());
@ -121,7 +135,12 @@ public class DaprClientGrpcTest {
.thenReturn(settableFuture); .thenReturn(settableFuture);
when(mockSerializer.serialize(any())).thenThrow(IOException.class); when(mockSerializer.serialize(any())).thenThrow(IOException.class);
Mono<Void> result = adapter.publishEvent("pubsubname","topic", "{invalid-json"); Mono<Void> result = adapter.publishEvent("pubsubname","topic", "{invalid-json");
result.block();
assertThrowsDaprException(
IOException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test @Test
@ -168,25 +187,25 @@ public class DaprClientGrpcTest {
@Test @Test
public void invokeBindingIllegalArgumentExceptionTest() { public void invokeBindingIllegalArgumentExceptionTest() {
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty binding name // empty binding name
adapter.invokeBinding("", "MyOperation", "request".getBytes(), Collections.EMPTY_MAP).block(); adapter.invokeBinding("", "MyOperation", "request".getBytes(), Collections.EMPTY_MAP).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null binding name // null binding name
adapter.invokeBinding(null, "MyOperation", "request".getBytes(), Collections.EMPTY_MAP).block(); adapter.invokeBinding(null, "MyOperation", "request".getBytes(), Collections.EMPTY_MAP).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null binding operation // null binding operation
adapter.invokeBinding("BindingName", null, "request".getBytes(), Collections.EMPTY_MAP).block(); adapter.invokeBinding("BindingName", null, "request".getBytes(), Collections.EMPTY_MAP).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty binding operation // empty binding operation
adapter.invokeBinding("BindingName", "", "request".getBytes(), Collections.EMPTY_MAP).block(); adapter.invokeBinding("BindingName", "", "request".getBytes(), Collections.EMPTY_MAP).block();
}); });
} }
@Test(expected = RuntimeException.class) @Test
public void invokeBindingSerializeException() throws IOException { public void invokeBindingSerializeException() throws IOException {
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class); DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
adapter = new DaprClientGrpc(closeable, client, mockSerializer, new DefaultObjectSerializer()); adapter = new DaprClientGrpc(closeable, client, mockSerializer, new DefaultObjectSerializer());
@ -195,18 +214,28 @@ public class DaprClientGrpcTest {
.thenReturn(settableFuture); .thenReturn(settableFuture);
when(mockSerializer.serialize(any())).thenThrow(IOException.class); when(mockSerializer.serialize(any())).thenThrow(IOException.class);
Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request".getBytes(), Collections.EMPTY_MAP); Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request".getBytes(), Collections.EMPTY_MAP);
result.block();
assertThrowsDaprException(
IOException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeBindingExceptionThrownTest() { public void invokeBindingExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeBinding(any(DaprProtos.InvokeBindingRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request"); Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request");
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeBindingCallbackExceptionThrownTest() { public void invokeBindingCallbackExceptionThrownTest() {
SettableFuture<DaprProtos.InvokeBindingResponse> settableFuture = SettableFuture.create(); SettableFuture<DaprProtos.InvokeBindingResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -217,7 +246,12 @@ public class DaprClientGrpcTest {
when(client.invokeBinding(any(DaprProtos.InvokeBindingRequest.class))) when(client.invokeBinding(any(DaprProtos.InvokeBindingRequest.class)))
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request"); Mono<Void> result = adapter.invokeBinding("BindingName", "MyOperation", "request");
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -314,33 +348,48 @@ public class DaprClientGrpcTest {
assertFalse(callback.wasCalled); assertFalse(callback.wasCalled);
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceVoidExceptionThrownTest() { public void invokeServiceVoidExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<Void> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE); Mono<Void> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceIllegalArgumentExceptionThrownTest() { public void invokeServiceIllegalArgumentExceptionThrownTest() {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenReturn(settableFuture); .thenReturn(settableFuture);
// HttpExtension cannot be null // HttpExtension cannot be null
Mono<Void> result = adapter.invokeService("appId", "method", "request", null); Mono<Void> result = adapter.invokeService("appId", "method", "request", null);
result.block();
assertThrowsDaprException(
IllegalArgumentException.class,
"UNKNOWN",
"UNKNOWN: HttpExtension cannot be null. Use HttpExtension.NONE instead.",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceEmptyRequestVoidExceptionThrownTest() { public void invokeServiceEmptyRequestVoidExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<Void> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null); Mono<Void> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceVoidCallbackExceptionThrownTest() { public void invokeServiceVoidCallbackExceptionThrownTest() {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -350,7 +399,12 @@ public class DaprClientGrpcTest {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<Void> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE); Mono<Void> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -384,31 +438,46 @@ public class DaprClientGrpcTest {
assertTrue(callback.wasCalled); assertTrue(callback.wasCalled);
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceExceptionThrownTest() { public void invokeServiceExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<String> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE, null, String.class); Mono<String> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE, null, String.class);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestClassExceptionThrownTest() { public void invokeServiceNoRequestClassExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<String> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null, String.class); Mono<String> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null, String.class);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestTypeRefExceptionThrownTest() { public void invokeServiceNoRequestTypeRefExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<String> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null, TypeRef.STRING); Mono<String> result = adapter.invokeService("appId", "method", HttpExtension.NONE, (Map<String, String>)null, TypeRef.STRING);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceCallbackExceptionThrownTest() { public void invokeServiceCallbackExceptionThrownTest() {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -418,7 +487,12 @@ public class DaprClientGrpcTest {
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<String> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE, null, String.class); Mono<String> result = adapter.invokeService("appId", "method", "request", HttpExtension.NONE, null, String.class);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -482,15 +556,20 @@ public class DaprClientGrpcTest {
assertEquals(object.value, resultObject.value); assertEquals(object.value, resultObject.value);
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestBodyExceptionThrownTest() { public void invokeServiceNoRequestBodyExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<String> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE, String.class); Mono<String> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE, String.class);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestCallbackExceptionThrownTest() { public void invokeServiceNoRequestCallbackExceptionThrownTest() {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -500,7 +579,12 @@ public class DaprClientGrpcTest {
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<String> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE, String.class); Mono<String> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE, String.class);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -536,17 +620,22 @@ public class DaprClientGrpcTest {
assertEquals(object.value, resultObject.value); assertEquals(object.value, resultObject.value);
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceByteRequestExceptionThrownTest() throws IOException { public void invokeServiceByteRequestExceptionThrownTest() throws IOException {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
String request = "Request"; String request = "Request";
byte[] byteRequest = serializer.serialize(request); byte[] byteRequest = serializer.serialize(request);
Mono<byte[]> result = adapter.invokeService("appId", "method", byteRequest, HttpExtension.NONE, byte[].class); Mono<byte[]> result = adapter.invokeService("appId", "method", byteRequest, HttpExtension.NONE, byte[].class);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceByteRequestCallbackExceptionThrownTest() throws IOException { public void invokeServiceByteRequestCallbackExceptionThrownTest() throws IOException {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -559,7 +648,12 @@ public class DaprClientGrpcTest {
Mono<byte[]> result = Mono<byte[]> result =
adapter.invokeService("appId", "method", byteRequest, HttpExtension.NONE,(HashMap<String, String>) null); adapter.invokeService("appId", "method", byteRequest, HttpExtension.NONE,(HashMap<String, String>) null);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -598,15 +692,20 @@ public class DaprClientGrpcTest {
assertEquals(resultObj, serializer.deserialize(byteOutput, MyObject.class)); assertEquals(resultObj, serializer.deserialize(byteOutput, MyObject.class));
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestNoClassBodyExceptionThrownTest() { public void invokeServiceNoRequestNoClassBodyExceptionThrownTest() {
when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class))) when(client.invokeService(any(DaprProtos.InvokeServiceRequest.class)))
.thenThrow(RuntimeException.class); .thenThrow(RuntimeException.class);
Mono<Void> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE); Mono<Void> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void invokeServiceNoRequestNoClassCallbackExceptionThrownTest() { public void invokeServiceNoRequestNoClassCallbackExceptionThrownTest() {
SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create(); SettableFuture<CommonProtos.InvokeResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -616,7 +715,12 @@ public class DaprClientGrpcTest {
.thenReturn(settableFuture); .thenReturn(settableFuture);
Mono<Void> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE); Mono<Void> result = adapter.invokeService("appId", "method", (Object)null, HttpExtension.NONE);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -670,33 +774,38 @@ public class DaprClientGrpcTest {
@Test @Test
public void getStateIllegalArgumentExceptionTest() { public void getStateIllegalArgumentExceptionTest() {
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.getState("", key, String.class).block(); adapter.getState("", key, String.class).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.getState(null, key, String.class).block(); adapter.getState(null, key, String.class).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null key // null key
adapter.getState(STATE_STORE_NAME, (String)null, String.class).block(); adapter.getState(STATE_STORE_NAME, (String)null, String.class).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty key // empty key
adapter.getState(STATE_STORE_NAME, "", String.class).block(); adapter.getState(STATE_STORE_NAME, "", String.class).block();
}); });
} }
@Test(expected = RuntimeException.class) @Test
public void getStateExceptionThrownTest() { public void getStateExceptionThrownTest() {
when(client.getState(any(io.dapr.v1.DaprProtos.GetStateRequest.class))).thenThrow(RuntimeException.class); when(client.getState(any(io.dapr.v1.DaprProtos.GetStateRequest.class))).thenThrow(RuntimeException.class);
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
Mono<State<String>> result = adapter.getState(STATE_STORE_NAME, key, String.class); Mono<State<String>> result = adapter.getState(STATE_STORE_NAME, key, String.class);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void getStateCallbackExceptionThrownTest() { public void getStateCallbackExceptionThrownTest() {
SettableFuture<DaprProtos.GetStateResponse> settableFuture = SettableFuture.create(); SettableFuture<DaprProtos.GetStateResponse> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -708,7 +817,12 @@ public class DaprClientGrpcTest {
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
Mono<State<String>> result = adapter.getState(STATE_STORE_NAME, key, String.class); Mono<State<String>> result = adapter.getState(STATE_STORE_NAME, key, String.class);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -829,20 +943,20 @@ public class DaprClientGrpcTest {
@Test @Test
public void getStatesIllegalArgumentExceptionTest() { public void getStatesIllegalArgumentExceptionTest() {
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.getStates("", Collections.singletonList("100"), String.class).block(); adapter.getStates("", Collections.singletonList("100"), String.class).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.getStates(null, Collections.singletonList("100"), String.class).block(); adapter.getStates(null, Collections.singletonList("100"), String.class).block();
}); });
assertThrows(NullPointerException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null key // null key
// null pointer exception due to keys being converted to an unmodifiable list // null pointer exception due to keys being converted to an unmodifiable list
adapter.getStates(STATE_STORE_NAME, null, String.class).block(); adapter.getStates(STATE_STORE_NAME, null, String.class).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty key list // empty key list
adapter.getStates(STATE_STORE_NAME, Collections.emptyList(), String.class).block(); adapter.getStates(STATE_STORE_NAME, Collections.emptyList(), String.class).block();
}); });
@ -850,7 +964,7 @@ public class DaprClientGrpcTest {
GetStatesRequest req = new GetStatesRequestBuilder(STATE_STORE_NAME, Collections.singletonList("100")) GetStatesRequest req = new GetStatesRequestBuilder(STATE_STORE_NAME, Collections.singletonList("100"))
.withParallelism(-1) .withParallelism(-1)
.build(); .build();
assertThrows(IllegalArgumentException.class, () -> adapter.getStates(req, TypeRef.BOOLEAN).block()); assertThrowsDaprException(IllegalArgumentException.class, () -> adapter.getStates(req, TypeRef.BOOLEAN).block());
} }
@Test @Test
@ -1029,36 +1143,41 @@ public class DaprClientGrpcTest {
assertEquals("not found", result.stream().skip(1).findFirst().get().getError()); assertEquals("not found", result.stream().skip(1).findFirst().get().getError());
} }
@Test(expected = RuntimeException.class) @Test
public void deleteStateExceptionThrowTest() { public void deleteStateExceptionThrowTest() {
when(client.deleteState(any(io.dapr.v1.DaprProtos.DeleteStateRequest.class))).thenThrow(RuntimeException.class); when(client.deleteState(any(io.dapr.v1.DaprProtos.DeleteStateRequest.class))).thenThrow(RuntimeException.class);
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
Mono<Void> result = adapter.deleteState(STATE_STORE_NAME, key.getKey(), key.getEtag(), key.getOptions()); Mono<Void> result = adapter.deleteState(STATE_STORE_NAME, key.getKey(), key.getEtag(), key.getOptions());
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test @Test
public void deleteStateIllegalArgumentExceptionTest() { public void deleteStateIllegalArgumentExceptionTest() {
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.deleteState("", key.getKey(), "etag", null).block(); adapter.deleteState("", key.getKey(), "etag", null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.deleteState(null, key.getKey(), "etag", null).block(); adapter.deleteState(null, key.getKey(), "etag", null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.deleteState(STATE_STORE_NAME, null, "etag", null).block(); adapter.deleteState(STATE_STORE_NAME, null, "etag", null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.deleteState(STATE_STORE_NAME, "", "etag", null).block(); adapter.deleteState(STATE_STORE_NAME, "", "etag", null).block();
}); });
} }
@Test(expected = RuntimeException.class) @Test
public void deleteStateCallbackExcpetionThrownTest() { public void deleteStateCallbackExcpetionThrownTest() {
SettableFuture<Empty> settableFuture = SettableFuture.create(); SettableFuture<Empty> settableFuture = SettableFuture.create();
RuntimeException ex = new RuntimeException("An Exception"); RuntimeException ex = new RuntimeException("An Exception");
@ -1069,7 +1188,12 @@ public class DaprClientGrpcTest {
State<String> key = buildStateKey(null, "Key1", "ETag1", null); State<String> key = buildStateKey(null, "Key1", "ETag1", null);
Mono<Void> result = adapter.deleteState(STATE_STORE_NAME, key.getKey(), key.getEtag(), key.getOptions()); Mono<Void> result = adapter.deleteState(STATE_STORE_NAME, key.getKey(), key.getEtag(), key.getOptions());
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -1190,17 +1314,17 @@ public class DaprClientGrpcTest {
TransactionalStateOperation<String> upsertOperation = new TransactionalStateOperation<>( TransactionalStateOperation<String> upsertOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.UPSERT, TransactionalStateOperation.OperationType.UPSERT,
key); key);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.executeTransaction("", Collections.singletonList(upsertOperation)).block(); adapter.executeTransaction("", Collections.singletonList(upsertOperation)).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null state store name // null state store name
adapter.executeTransaction(null, Collections.singletonList(upsertOperation)).block(); adapter.executeTransaction(null, Collections.singletonList(upsertOperation)).block();
}); });
} }
@Test(expected = RuntimeException.class) @Test
public void executeTransactionSerializerExceptionTest() throws IOException { public void executeTransactionSerializerExceptionTest() throws IOException {
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class); DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
adapter = new DaprClientGrpc(closeable, client, mockSerializer, mockSerializer); adapter = new DaprClientGrpc(closeable, client, mockSerializer, mockSerializer);
@ -1220,7 +1344,12 @@ public class DaprClientGrpcTest {
.withTransactionalStates(upsertOperation) .withTransactionalStates(upsertOperation)
.build(); .build();
Mono<Response<Void>> result = adapter.executeTransaction(request); Mono<Response<Void>> result = adapter.executeTransaction(request);
result.block();
assertThrowsDaprException(
IOException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test @Test
@ -1278,7 +1407,7 @@ public class DaprClientGrpcTest {
assertTrue(callback.wasCalled); assertTrue(callback.wasCalled);
} }
@Test(expected = RuntimeException.class) @Test
public void executeTransactionExceptionThrownTest() { public void executeTransactionExceptionThrownTest() {
String etag = "ETag1"; String etag = "ETag1";
String key = "key1"; String key = "key1";
@ -1291,10 +1420,15 @@ public class DaprClientGrpcTest {
TransactionalStateOperation.OperationType.UPSERT, TransactionalStateOperation.OperationType.UPSERT,
stateKey); stateKey);
Mono<Void> result = adapter.executeTransaction(STATE_STORE_NAME, Collections.singletonList(operation)); Mono<Void> result = adapter.executeTransaction(STATE_STORE_NAME, Collections.singletonList(operation));
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void executeTransactionCallbackExceptionTest() { public void executeTransactionCallbackExceptionTest() {
String etag = "ETag1"; String etag = "ETag1";
String key = "key1"; String key = "key1";
@ -1312,32 +1446,42 @@ public class DaprClientGrpcTest {
stateKey); stateKey);
Mono<Void> result = adapter.executeTransaction(STATE_STORE_NAME, Collections.singletonList(operation)); Mono<Void> result = adapter.executeTransaction(STATE_STORE_NAME, Collections.singletonList(operation));
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: ex",
() -> result.block());
} }
@Test @Test
public void saveStatesIllegalArgumentExceptionTest() { public void saveStatesIllegalArgumentExceptionTest() {
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.saveStates("", Collections.emptyList()).block(); adapter.saveStates("", Collections.emptyList()).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty state store name // empty state store name
adapter.saveStates(null, Collections.emptyList()).block(); adapter.saveStates(null, Collections.emptyList()).block();
}); });
} }
@Test(expected = RuntimeException.class) @Test
public void saveStateExceptionThrownTest() { public void saveStateExceptionThrownTest() {
String key = "key1"; String key = "key1";
String etag = "ETag1"; String etag = "ETag1";
String value = "State value"; String value = "State value";
when(client.saveState(any(io.dapr.v1.DaprProtos.SaveStateRequest.class))).thenThrow(RuntimeException.class); when(client.saveState(any(io.dapr.v1.DaprProtos.SaveStateRequest.class))).thenThrow(RuntimeException.class);
Mono<Void> result = adapter.saveState(STATE_STORE_NAME, key, etag, value, null); Mono<Void> result = adapter.saveState(STATE_STORE_NAME, key, etag, value, null);
result.block();
assertThrowsDaprException(
RuntimeException.class,
"UNKNOWN",
"UNKNOWN: ",
() -> result.block());
} }
@Test(expected = RuntimeException.class) @Test
public void saveStateCallbackExceptionThrownTest() { public void saveStateCallbackExceptionThrownTest() {
String key = "key1"; String key = "key1";
String etag = "ETag1"; String etag = "ETag1";
@ -1349,7 +1493,12 @@ public class DaprClientGrpcTest {
when(client.saveState(any(io.dapr.v1.DaprProtos.SaveStateRequest.class))).thenReturn(settableFuture); when(client.saveState(any(io.dapr.v1.DaprProtos.SaveStateRequest.class))).thenReturn(settableFuture);
Mono<Void> result = adapter.saveState(STATE_STORE_NAME, key, etag, value, null); Mono<Void> result = adapter.saveState(STATE_STORE_NAME, key, etag, value, null);
settableFuture.setException(ex); settableFuture.setException(ex);
result.block();
assertThrowsDaprException(
ExecutionException.class,
"UNKNOWN",
"UNKNOWN: java.lang.RuntimeException: An Exception",
() -> result.block());
} }
@Test @Test
@ -1478,22 +1627,25 @@ public class DaprClientGrpcTest {
*/ */
@Test @Test
public void getStateDeleteStateThenBlockDeleteThenBlockGet() throws Exception { public void getStateThenDelete() throws Exception {
String etag = "ETag1"; String etag = "ETag1";
String key1 = "key1"; String key1 = "key1";
String expectedValue1 = "Expected state 1"; String expectedValue1 = "Expected state 1";
String key2 = "key2"; String key2 = "key2";
String expectedValue2 = "Expected state 2"; String expectedValue2 = "Expected state 2";
State<String> expectedState1 = buildStateKey(expectedValue1, key1, etag, new HashMap<>(), null); State<String> expectedState1 = buildStateKey(expectedValue1, key1, etag, new HashMap<>(), null);
State<String> expectedState2 = buildStateKey(expectedValue2, key2, etag, new HashMap<>(), null);
Map<String, SettableFuture<DaprProtos.GetStateResponse>> futuresMap = new HashMap<>(); Map<String, SettableFuture<DaprProtos.GetStateResponse>> futuresMap = new HashMap<>();
futuresMap.put(key1, buildFutureGetStateEnvelop(expectedValue1, etag)); futuresMap.put(key1, buildFutureGetStateEnvelop(expectedValue1, etag));
futuresMap.put(key2, buildFutureGetStateEnvelop(expectedValue2, etag)); futuresMap.put(key2, buildFutureGetStateEnvelop(expectedValue2, etag));
when(client.getState(argThat(new GetStateRequestKeyMatcher(key1)))).thenReturn(futuresMap.get(key1)); when(client.getState(argThat(new GetStateRequestKeyMatcher(key1)))).thenReturn(futuresMap.get(key1));
when(client.getState(argThat(new GetStateRequestKeyMatcher(key2)))).thenReturn(futuresMap.get(key2));
State<String> keyRequest1 = buildStateKey(null, key1, etag, null); State<String> keyRequest1 = buildStateKey(null, key1, etag, null);
Mono<State<String>> resultGet1 = adapter.getState(STATE_STORE_NAME, keyRequest1, String.class); Mono<State<String>> resultGet1 = adapter.getState(STATE_STORE_NAME, keyRequest1, String.class);
assertEquals(expectedState1, resultGet1.block()); assertEquals(expectedState1, resultGet1.block());
State<String> keyRequest2 = buildStateKey(null, key2, etag, null); State<String> keyRequest2 = buildStateKey(null, key2, etag, null);
Mono<State<String>> resultGet2 = adapter.getState(STATE_STORE_NAME, keyRequest2, String.class); Mono<State<String>> resultGet2 = adapter.getState(STATE_STORE_NAME, keyRequest2, String.class);
assertEquals(expectedState2, resultGet2.block());
SettableFuture<Empty> settableFutureDelete = SettableFuture.create(); SettableFuture<Empty> settableFutureDelete = SettableFuture.create();
MockCallback<Empty> callbackDelete = new MockCallback<>(Empty.newBuilder().build()); MockCallback<Empty> callbackDelete = new MockCallback<>(Empty.newBuilder().build());
@ -1505,11 +1657,6 @@ public class DaprClientGrpcTest {
settableFutureDelete.set(Empty.newBuilder().build()); settableFutureDelete.set(Empty.newBuilder().build());
resultDelete.block(); resultDelete.block();
assertTrue(callbackDelete.wasCalled); assertTrue(callbackDelete.wasCalled);
futuresMap.replace(key2, null);
when(client.getState(argThat(new GetStateRequestKeyMatcher(key2)))).thenReturn(futuresMap.get(key2));
State<String> state2 = resultGet2.block();
assertNull(state2);
} }
@Test @Test
@ -1575,24 +1722,24 @@ public class DaprClientGrpcTest {
return settableFuture; return settableFuture;
}); });
assertThrows(RuntimeException.class, () -> adapter.getSecret(SECRET_STORE_NAME, "key").block()); assertThrowsDaprException(ExecutionException.class, () -> adapter.getSecret(SECRET_STORE_NAME, "key").block());
} }
@Test @Test
public void getSecretsIllegalArgumentException() { public void getSecretsIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty secret store name // empty secret store name
adapter.getSecret("", "key").block(); adapter.getSecret("", "key").block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null secret store name // null secret store name
adapter.getSecret(null, "key").block(); adapter.getSecret(null, "key").block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty key // empty key
adapter.getSecret(SECRET_STORE_NAME, "").block(); adapter.getSecret(SECRET_STORE_NAME, "").block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null key // null key
adapter.getSecret(SECRET_STORE_NAME, null).block(); adapter.getSecret(SECRET_STORE_NAME, null).block();
}); });
@ -1821,4 +1968,8 @@ public class DaprClientGrpcTest {
return "<Has property of certain value (propName: " + propValue + ") matcher>"; return "<Has property of certain value (propName: " + propValue + ") matcher>";
} }
} }
private static StatusRuntimeException newStatusRuntimeException(String status, String message) {
return new StatusRuntimeException(Status.fromCode(Status.Code.valueOf(status)).withDescription(message));
}
} }

View File

@ -4,8 +4,10 @@
*/ */
package io.dapr.client; package io.dapr.client;
import com.fasterxml.jackson.core.JsonParseException;
import io.dapr.client.domain.DeleteStateRequestBuilder; import io.dapr.client.domain.DeleteStateRequestBuilder;
import io.dapr.client.domain.GetStateRequestBuilder; import io.dapr.client.domain.GetStateRequestBuilder;
import io.dapr.client.domain.GetStatesRequestBuilder;
import io.dapr.client.domain.HttpExtension; import io.dapr.client.domain.HttpExtension;
import io.dapr.client.domain.Response; import io.dapr.client.domain.Response;
import io.dapr.client.domain.State; import io.dapr.client.domain.State;
@ -14,12 +16,16 @@ import io.dapr.client.domain.TransactionalStateOperation;
import io.dapr.config.Properties; import io.dapr.config.Properties;
import io.dapr.utils.TypeRef; import io.dapr.utils.TypeRef;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.mock.Behavior; import okhttp3.mock.Behavior;
import okhttp3.mock.MediaTypes;
import okhttp3.mock.MockInterceptor; import okhttp3.mock.MockInterceptor;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
@ -28,6 +34,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static io.dapr.utils.TestUtils.assertThrowsDaprException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
@ -53,7 +60,7 @@ public class DaprClientHttpTest {
private MockInterceptor mockInterceptor; private MockInterceptor mockInterceptor;
@Before @Before
public void setUp() throws Exception { public void setUp() {
mockInterceptor = new MockInterceptor(Behavior.UNORDERED); mockInterceptor = new MockInterceptor(Behavior.UNORDERED);
okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build(); okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
} }
@ -82,16 +89,15 @@ public class DaprClientHttpTest {
assertNull(mono.block()); assertNull(mono.block());
} }
@Test(expected = IllegalArgumentException.class) @Test
public void publishEventIfTopicIsNull() { public void publishEventIfTopicIsNullOrEmpty() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/publish/mypubsubname/A")
.respond(EXPECTED_RESULT);
String event = "{ \"message\": \"This is a test\" }"; String event = "{ \"message\": \"This is a test\" }";
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.publishEvent("mypubsubname", "", event); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.publishEvent("mypubsubname", null, event).block());
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.publishEvent("mypubsubname", "", event).block());
} }
@Test @Test
@ -106,7 +112,7 @@ public class DaprClientHttpTest {
// Should not throw exception because did not call block() on mono above. // Should not throw exception because did not call block() on mono above.
} }
@Test(expected = IllegalArgumentException.class) @Test
public void invokeServiceVerbNull() { public void invokeServiceVerbNull() {
mockInterceptor.addRule() mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/publish/A") .post("http://127.0.0.1:3000/v1.0/publish/A")
@ -114,46 +120,49 @@ public class DaprClientHttpTest {
String event = "{ \"message\": \"This is a test\" }"; String event = "{ \"message\": \"This is a test\" }";
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeService(null, "", "", null, null, (Class)null); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.invokeService(null, "", "", null, null, (Class)null).block());
} }
@Test @Test
public void invokeServiceIllegalArgumentException() { public void invokeServiceIllegalArgumentException() {
mockInterceptor.addRule() mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/publish/A") .get("http://127.0.0.1:3000/v1.0/invoke/41/method/badorder")
.respond(EXPECTED_RESULT); .respond("INVALID JSON");
String event = "{ \"message\": \"This is a test\" }";
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null HttpMethod // null HttpMethod
daprClientHttp.invokeService("1", "2", "3", new HttpExtension(null, null), null, (Class)null).block(); daprClientHttp.invokeService("1", "2", "3", new HttpExtension(null, null), null, (Class)null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null HttpExtension // null HttpExtension
daprClientHttp.invokeService("1", "2", "3", null, null, (Class)null).block(); daprClientHttp.invokeService("1", "2", "3", null, null, (Class)null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty appId // empty appId
daprClientHttp.invokeService("", "1", null, HttpExtension.GET, null, (Class)null).block(); daprClientHttp.invokeService("", "1", null, HttpExtension.GET, null, (Class)null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null appId, empty method // null appId, empty method
daprClientHttp.invokeService(null, "", null, HttpExtension.POST, null, (Class)null).block(); daprClientHttp.invokeService(null, "", null, HttpExtension.POST, null, (Class)null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// empty method // empty method
daprClientHttp.invokeService("1", "", null, HttpExtension.PUT, null, (Class)null).block(); daprClientHttp.invokeService("1", "", null, HttpExtension.PUT, null, (Class)null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
// null method // null method
daprClientHttp.invokeService("1", null, null, HttpExtension.DELETE, null, (Class)null).block(); daprClientHttp.invokeService("1", null, null, HttpExtension.DELETE, null, (Class)null).block();
}); });
assertThrowsDaprException(JsonParseException.class, () -> {
// invalid JSON response
daprClientHttp.invokeService("41", "badorder", null, HttpExtension.GET, null, String.class).block();
});
} }
@Test(expected = IllegalArgumentException.class) @Test
public void invokeServiceMethodNull() { public void invokeServiceMethodNull() {
mockInterceptor.addRule() mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/publish/A") .post("http://127.0.0.1:3000/v1.0/publish/A")
@ -161,24 +170,34 @@ public class DaprClientHttpTest {
String event = "{ \"message\": \"This is a test\" }"; String event = "{ \"message\": \"This is a test\" }";
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeService("1", "", null, HttpExtension.POST, null, (Class)null); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.invokeService("1", "", null, HttpExtension.POST, null, (Class)null).block());
} }
@Test @Test
public void invokeService() { public void invokeService() {
mockInterceptor.addRule() mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder") .get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder")
.respond("\"hello world\""); .respond("\"hello world\"");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<String> mono = daprClientHttp.invokeService("41", "neworder", null, HttpExtension.GET, null, String.class); Mono<String> mono = daprClientHttp.invokeService("41", "neworder", null, HttpExtension.GET, null, String.class);
assertEquals("hello world", mono.block()); assertEquals("hello world", mono.block());
} }
@Test
public void invokeServiceNullResponse() {
mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder")
.respond(new byte[0]);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
Mono<String> mono = daprClientHttp.invokeService("41", "neworder", null, HttpExtension.GET, null, String.class);
assertNull(mono.block());
}
@Test @Test
public void simpleInvokeService() { public void simpleInvokeService() {
Map<String, String> map = new HashMap<>();
mockInterceptor.addRule() mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder") .get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder")
.respond(EXPECTED_RESULT); .respond(EXPECTED_RESULT);
@ -256,14 +275,62 @@ public class DaprClientHttpTest {
public void invokeBinding() { public void invokeBinding() {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
mockInterceptor.addRule() mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/bindings/sample-topic") .post("http://127.0.0.1:3000/v1.0/bindings/sample-topic")
.respond(""); .respond("");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", ""); Mono<Void> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", "");
assertNull(mono.block()); assertNull(mono.block());
} }
@Test
public void invokeBindingNullData() {
Map<String, String> map = new HashMap<>();
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/bindings/sample-topic")
.respond("");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", null);
assertNull(mono.block());
}
@Test
public void invokeBindingErrors() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/bindings/sample-topic")
.respond("NOT VALID JSON");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.invokeBinding(null, "myoperation", "").block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.invokeBinding("", "myoperation", "").block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.invokeBinding("topic", null, "").block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.invokeBinding("topic", "", "").block();
});
assertThrowsDaprException(JsonParseException.class, () -> {
daprClientHttp.invokeBinding("sample-topic", "op", "data", String.class).block();
});
}
@Test
public void invokeBindingResponseNull() {
Map<String, String> map = new HashMap<>();
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/bindings/sample-topic")
.respond(new byte[0]);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
Mono<String> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", "", null, String.class);
assertNull(mono.block());
}
@Test @Test
public void invokeBindingResponseObject() { public void invokeBindingResponseObject() {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
@ -284,7 +351,7 @@ public class DaprClientHttpTest {
.respond("1.5"); .respond("1.5");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Double> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", "", null, double.class); Mono<Double> mono = daprClientHttp.invokeBinding("sample-topic", "myoperation", "", map, double.class);
assertEquals(1.5, mono.block(), 0.0001); assertEquals(1.5, mono.block(), 0.0001);
} }
@ -348,7 +415,7 @@ public class DaprClientHttpTest {
assertEquals(1, (int)mono.block()); assertEquals(1, (int)mono.block());
} }
@Test(expected = IllegalArgumentException.class) @Test
public void invokeBindingNullName() { public void invokeBindingNullName() {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
mockInterceptor.addRule() mockInterceptor.addRule()
@ -356,11 +423,11 @@ public class DaprClientHttpTest {
.respond(EXPECTED_RESULT); .respond(EXPECTED_RESULT);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeBinding(null, "myoperation", ""); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.invokeBinding(null, "myoperation", "").block());
} }
@Test(expected = IllegalArgumentException.class) @Test
public void invokeBindingNullOpName() { public void invokeBindingNullOpName() {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
mockInterceptor.addRule() mockInterceptor.addRule()
@ -368,8 +435,8 @@ public class DaprClientHttpTest {
.respond(EXPECTED_RESULT); .respond(EXPECTED_RESULT);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.invokeBinding("sample-topic", null, ""); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.invokeBinding("sample-topic", null, "").block());
} }
@Test @Test
@ -384,6 +451,37 @@ public class DaprClientHttpTest {
// No exception is thrown because did not call block() on mono above. // No exception is thrown because did not call block() on mono above.
} }
@Test
public void getStatesErrors() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore/bulk")
.respond("NOT VALID JSON");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getStates(STATE_STORE_NAME, null, String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getStates(STATE_STORE_NAME, new ArrayList<>(), String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getStates(null, Arrays.asList("100", "200"), String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getStates("", Arrays.asList("100", "200"), String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getStates(
new GetStatesRequestBuilder(STATE_STORE_NAME, "100").withParallelism(-1).build(),
TypeRef.get(String.class)).block();
});
assertThrowsDaprException(JsonParseException.class, () -> {
daprClientHttp.getStates(
new GetStatesRequestBuilder(STATE_STORE_NAME, "100").build(),
TypeRef.get(String.class)).block();
});
}
@Test @Test
public void getStatesString() { public void getStatesString() {
mockInterceptor.addRule() mockInterceptor.addRule()
@ -504,14 +602,31 @@ public class DaprClientHttpTest {
StateOptions stateOptions = mock(StateOptions.class); StateOptions stateOptions = mock(StateOptions.class);
State<String> stateKeyValue = new State<>("value", "key", "etag", stateOptions); State<String> stateKeyValue = new State<>("value", "key", "etag", stateOptions);
State<String> stateKeyNull = new State<>("value", null, "etag", stateOptions); State<String> stateKeyNull = new State<>("value", null, "etag", stateOptions);
State<String> stateKeyEmpty = new State<>("value", "", "etag", stateOptions);
State<String> stateKeyBadPayload = new State<>("value", "keyBadPayload", "etag", stateOptions);
mockInterceptor.addRule() mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/state/MyStateStore/key") .get("http://127.0.0.1:3000/v1.0/state/MyStateStore/key")
.respond("\"" + EXPECTED_RESULT + "\""); .respond("\"" + EXPECTED_RESULT + "\"");
mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/state/MyStateStore/keyBadPayload")
.respond("NOT VALID");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getState(STATE_STORE_NAME, stateKeyNull, String.class).block(); daprClientHttp.getState(STATE_STORE_NAME, stateKeyNull, String.class).block();
}); });
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getState(STATE_STORE_NAME, stateKeyEmpty, String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getState(null, stateKeyValue, String.class).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getState("", stateKeyValue, String.class).block();
});
assertThrowsDaprException(JsonParseException.class, () -> {
daprClientHttp.getState(STATE_STORE_NAME, stateKeyBadPayload, String.class).block();
});
Mono<State<String>> mono = daprClientHttp.getState(STATE_STORE_NAME, stateKeyValue, String.class); Mono<State<String>> mono = daprClientHttp.getState(STATE_STORE_NAME, stateKeyValue, String.class);
State<String> result = mono.block(); State<String> result = mono.block();
assertNotNull(result); assertNotNull(result);
@ -582,20 +697,19 @@ public class DaprClientHttpTest {
assertNull(mono.block()); assertNull(mono.block());
} }
@Test(expected = IllegalArgumentException.class) @Test
public void saveStateNullStateStoreName() { public void saveStatesErrors() {
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.saveStates(null, null); assertThrowsDaprException(IllegalArgumentException.class, () ->
assertNull(mono.block()); daprClientHttp.saveStates(null, null).block());
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.saveStates("", null).block());
} }
@Test @Test
public void saveStatesNull() { public void saveStatesNull() {
List<State<?>> stateKeyValueList = new ArrayList<>(); List<State<?>> stateKeyValueList = new ArrayList<>();
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore")
.respond(EXPECTED_RESULT);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.saveStates(STATE_STORE_NAME, null); Mono<Void> mono = daprClientHttp.saveStates(STATE_STORE_NAME, null);
@ -604,6 +718,19 @@ public class DaprClientHttpTest {
assertNull(mono1.block()); assertNull(mono1.block());
} }
@Test
public void saveStatesNullState() {
List<State<?>> stateKeyValueList = new ArrayList<>();
stateKeyValueList.add(null);
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore")
.respond(EXPECTED_RESULT);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono1 = daprClientHttp.saveStates(STATE_STORE_NAME, stateKeyValueList);
assertNull(mono1.block());
}
@Test @Test
public void saveStatesEtagNull() { public void saveStatesEtagNull() {
State<String> stateKeyValue = new State<>("value", "key", null, null); State<String> stateKeyValue = new State<>("value", "key", null, null);
@ -678,14 +805,94 @@ public class DaprClientHttpTest {
assertNull(mono.block()); assertNull(mono.block());
} }
@Test(expected = IllegalArgumentException.class) @Test
public void executeTransactionNullStateStoreName() { public void simpleExecuteTransactionNullEtag() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore/transaction")
.respond(EXPECTED_RESULT);
String etag = null;
String key = "key1";
String data = "my data";
StateOptions stateOptions = mock(StateOptions.class);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
Mono<Void> mono = daprClientHttp.executeTransaction(null, null);
State<String> stateKey = new State<>(data, key, etag, stateOptions);
TransactionalStateOperation<String> upsertOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.UPSERT,
stateKey);
TransactionalStateOperation<String> deleteOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.DELETE,
new State<>("deleteKey"));
Mono<Void> mono = daprClientHttp.executeTransaction(STATE_STORE_NAME, Arrays.asList(upsertOperation,
deleteOperation));
assertNull(mono.block()); assertNull(mono.block());
} }
@Test
public void simpleExecuteTransactionEmptyEtag() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore/transaction")
.respond(EXPECTED_RESULT);
String etag = "empty";
String key = "key1";
String data = "my data";
StateOptions stateOptions = mock(StateOptions.class);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
State<String> stateKey = new State<>(data, key, etag, stateOptions);
TransactionalStateOperation<String> upsertOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.UPSERT,
stateKey);
TransactionalStateOperation<String> deleteOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.DELETE,
new State<>("deleteKey"));
Mono<Void> mono = daprClientHttp.executeTransaction(STATE_STORE_NAME, Arrays.asList(upsertOperation,
deleteOperation));
assertNull(mono.block());
}
@Test
public void simpleExecuteTransactionNullOperationAndNullState() {
mockInterceptor.addRule()
.post("http://127.0.0.1:3000/v1.0/state/MyStateStore/transaction")
.respond(EXPECTED_RESULT);
String etag = null;
String key = "key1";
String data = "my data";
StateOptions stateOptions = mock(StateOptions.class);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
State<String> stateKey = new State<>(data, key, etag, stateOptions);
TransactionalStateOperation<String> upsertOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.UPSERT,
stateKey);
TransactionalStateOperation<String> deleteOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.DELETE,
new State<>("deleteKey"));
TransactionalStateOperation<String> nullStateOperation = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.DELETE,
null);
Mono<Void> mono = daprClientHttp.executeTransaction(STATE_STORE_NAME, Arrays.asList(
null,
nullStateOperation,
upsertOperation,
deleteOperation));
assertNull(mono.block());
}
@Test
public void executeTransactionErrors() {
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.executeTransaction(null, null).block());
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.executeTransaction("", null).block());
}
@Test @Test
public void simpleExecuteTransactionNull() { public void simpleExecuteTransactionNull() {
mockInterceptor.addRule() mockInterceptor.addRule()
@ -699,10 +906,6 @@ public class DaprClientHttpTest {
assertNull(mono.block()); assertNull(mono.block());
} }
/*
*/
@Test @Test
public void deleteState() { public void deleteState() {
StateOptions stateOptions = mock(StateOptions.class); StateOptions stateOptions = mock(StateOptions.class);
@ -779,22 +982,22 @@ public class DaprClientHttpTest {
.respond(EXPECTED_RESULT); .respond(EXPECTED_RESULT);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState(STATE_STORE_NAME, null, null, null).block(); daprClientHttp.deleteState(STATE_STORE_NAME, null, null, null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState(STATE_STORE_NAME, "", null, null).block(); daprClientHttp.deleteState(STATE_STORE_NAME, "", null, null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState(STATE_STORE_NAME, " ", null, null).block(); daprClientHttp.deleteState(STATE_STORE_NAME, " ", null, null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState(null, "key", null, null).block(); daprClientHttp.deleteState(null, "key", null, null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState("", "key", null, null).block(); daprClientHttp.deleteState("", "key", null, null).block();
}); });
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.deleteState(" ", "key", null, null).block(); daprClientHttp.deleteState(" ", "key", null, null).block();
}); });
} }
@ -806,7 +1009,7 @@ public class DaprClientHttpTest {
.respond("{ \"mysecretkey\": \"mysecretvalue\"}"); .respond("{ \"mysecretkey\": \"mysecretvalue\"}");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, null).block(); daprClientHttp.getSecret(SECRET_STORE_NAME, null).block();
}); });
Map<String, String> secret = daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block(); Map<String, String> secret = daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block();
@ -822,7 +1025,7 @@ public class DaprClientHttpTest {
.respond(""); .respond("");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> { assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, null).block(); daprClientHttp.getSecret(SECRET_STORE_NAME, null).block();
}); });
Map<String, String> secret = daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block(); Map<String, String> secret = daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block();
@ -833,20 +1036,50 @@ public class DaprClientHttpTest {
@Test @Test
public void getSecrets404() { public void getSecrets404() {
mockInterceptor.addRule() mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/secrets/MySecretStore/key") .get("http://127.0.0.1:3000/v1.0/secrets/MySecretStore/key")
.respond(404); .respond(404);
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalStateException.class, () -> { assertThrowsDaprException("UNKNOWN", () ->
daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block(); daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block()
}); );
} }
@Test(expected = IllegalArgumentException.class) @Test
public void getSecretsNullStoreName() { public void getSecrets404WithErrorCode() {
mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/secrets/MySecretStore/key")
.respond(404,
ResponseBody.create("" +
"{\"errorCode\":\"ERR_SECRET_STORE_NOT_FOUND\"," +
"\"message\":\"error message\"}", MediaTypes.MEDIATYPE_JSON));
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
daprClientHttp.getSecret(null, "key").block(); assertThrowsDaprException("ERR_SECRET_STORE_NOT_FOUND", "ERR_SECRET_STORE_NOT_FOUND: error message", () ->
daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block()
);
}
@Test
public void getSecretsErrors() {
mockInterceptor.addRule()
.get("http://127.0.0.1:3000/v1.0/secrets/MySecretStore/key")
.respond("INVALID JSON");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp);
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.getSecret(null, "key").block());
assertThrowsDaprException(IllegalArgumentException.class, () ->
daprClientHttp.getSecret("", "key").block());
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, null).block();
});
assertThrowsDaprException(IllegalArgumentException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, "").block();
});
assertThrowsDaprException(JsonParseException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block();
});
} }
@Test @Test
@ -859,10 +1092,6 @@ public class DaprClientHttpTest {
.respond("{ \"mysecretkey2\": \"mysecretvalue2\"}"); .respond("{ \"mysecretkey2\": \"mysecretvalue2\"}");
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
daprClientHttp = new DaprClientHttp(daprHttp); daprClientHttp = new DaprClientHttp(daprHttp);
assertThrows(IllegalArgumentException.class, () -> {
daprClientHttp.getSecret(SECRET_STORE_NAME, null).block();
});
{ {
Map<String, String> secret = daprClientHttp.getSecret( Map<String, String> secret = daprClientHttp.getSecret(
SECRET_STORE_NAME, SECRET_STORE_NAME,
@ -884,6 +1113,26 @@ public class DaprClientHttpTest {
} }
} }
@Test
public void closeException() {
DaprHttp daprHttp = Mockito.mock(DaprHttp.class);
Mockito.doThrow(new IllegalStateException()).when(daprHttp).close();
// This method does not throw DaprException because IOException is expected by the Closeable interface.
daprClientHttp = new DaprClientHttp(daprHttp);
assertThrowsDaprException(IllegalStateException.class, () -> daprClientHttp.close());
}
@Test
public void close() {
DaprHttp daprHttp = Mockito.mock(DaprHttp.class);
Mockito.doNothing().when(daprHttp).close();
// This method does not throw DaprException because IOException is expected by the Closeable interface.
daprClientHttp = new DaprClientHttp(daprHttp);
daprClientHttp.close();
}
public static class MyObject { public static class MyObject {
private Integer id; private Integer id;
private String value; private String value;

View File

@ -57,6 +57,6 @@ public class DaprHttpStub extends DaprHttp {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void close() throws IOException { public void close() {
} }
} }

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
package io.dapr.utils;
import io.dapr.exceptions.DaprException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
public final class TestUtils {
private TestUtils() {}
public static <T extends Throwable> void assertThrowsDaprException(Class<T> expectedType, Executable executable) {
Throwable cause = Assertions.assertThrows(DaprException.class, executable).getCause();
Assertions.assertNotNull(cause);
Assertions.assertEquals(expectedType, cause.getClass());
}
public static void assertThrowsDaprException(String expectedErrorCode, Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNull(daprException.getCause());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
}
public static void assertThrowsDaprException(
String expectedErrorCode,
String expectedErrorMessage,
Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNull(daprException.getCause());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
}
public static <T extends Throwable> void assertThrowsDaprException(
Class<T> expectedType,
String expectedErrorCode,
String expectedErrorMessage,
Executable executable) {
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertNotNull(daprException.getCause());
Assertions.assertEquals(expectedType, daprException.getCause().getClass());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
}
}