Skip to content

Commit

Permalink
Adds error payload to DaprException. (dapr#1009)
Browse files Browse the repository at this point in the history
* Adds error payload to DaprException.

Signed-off-by: Artur Souza <asouza.pro@gmail.com>

* Keep having http payload in exception message.

Signed-off-by: Artur Souza <asouza.pro@gmail.com>

* Fix example output.

Signed-off-by: Artur Souza <asouza.pro@gmail.com>

* Lint.

Signed-off-by: Artur Souza <asouza.pro@gmail.com>

* Fix test.

Signed-off-by: Artur Souza <asouza.pro@gmail.com>

---------

Signed-off-by: Artur Souza <asouza.pro@gmail.com>
  • Loading branch information
artursouza authored Feb 15, 2024
1 parent a3cc138 commit 81e6c4d
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 27 deletions.
8 changes: 2 additions & 6 deletions examples/src/main/java/io/dapr/examples/exception/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
import io.dapr.exceptions.DaprException;
import io.dapr.utils.TypeRef;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 1. Build and install jars:
* mvn clean install
Expand All @@ -45,10 +40,11 @@ public static void main(String[] args) throws Exception {
} catch (DaprException exception) {
System.out.println("Error code: " + exception.getErrorCode());
System.out.println("Error message: " + exception.getMessage());
System.out.println("Reason: " + exception.getStatusDetails().get(
System.out.println("Reason: " + exception.getErrorDetails().get(
DaprErrorDetails.ErrorDetailType.ERROR_INFO,
"reason",
TypeRef.STRING));
System.out.println("Error payload size: " + exception.getPayload().length);
}
}
System.out.println("Done");
Expand Down
4 changes: 4 additions & 0 deletions examples/src/main/java/io/dapr/examples/exception/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class Client {
DaprErrorDetails.ErrorDetailType.ERROR_INFO,
"reason",
TypeRef.STRING));
System.out.println("Error's payload size: " + exception.getPayload().length);
}
}
System.out.println("Done");
Expand All @@ -66,6 +67,7 @@ expected_stdout_lines:
- '== APP == Error code: INVALID_ARGUMENT'
- '== APP == Error message: INVALID_ARGUMENT: pubsub unknown_pubsub is not found'
- '== APP == Reason: DAPR_PUBSUB_NOT_FOUND'
- '== APP == Error payload size: 116'
background: true
sleep: 5
-->
Expand All @@ -84,6 +86,8 @@ Once running, the State Client Example should print the output as follows:
== APP == Error message: ERR_PUBSUB_NOT_FOUND: pubsub unknown_pubsub is not found
== APP == Reason: DAPR_PUBSUB_NOT_FOUND
== APP == Error payload size: 116
...
```
Expand Down
4 changes: 2 additions & 2 deletions sdk-tests/src/test/java/io/dapr/it/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ public static <T extends Throwable> void assertThrowsDaprExceptionWithReason(
DaprException daprException = Assertions.assertThrows(DaprException.class, executable);
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
Assertions.assertNotNull(daprException.getStatusDetails());
Assertions.assertNotNull(daprException.getErrorDetails());
Assertions.assertEquals(
expectedReason,
daprException.getStatusDetails().get(
daprException.getErrorDetails().get(
DaprErrorDetails.ErrorDetailType.ERROR_INFO,
"reason",
TypeRef.STRING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public void testInvokeException() throws Exception {
assertEquals("UNKNOWN", exception.getErrorCode());
assertNotNull(exception.getMessage());
assertTrue(exception.getMessage().contains("Internal Server Error"));
assertTrue(new String(exception.getPayload()).contains("Internal Server Error"));
}
}
}
12 changes: 6 additions & 6 deletions sdk/src/main/java/io/dapr/client/DaprHttp.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import io.dapr.client.domain.Metadata;
import io.dapr.config.Properties;
import io.dapr.exceptions.DaprError;
import io.dapr.exceptions.DaprErrorDetails;
import io.dapr.exceptions.DaprException;
import io.dapr.utils.Version;
import okhttp3.Call;
Expand Down Expand Up @@ -350,7 +349,7 @@ private static DaprError parseDaprError(byte[] json) {
try {
return DAPR_ERROR_DETAILS_OBJECT_MAPPER.readValue(json, DaprError.class);
} catch (IOException e) {
throw new DaprException("UNKNOWN", new String(json, StandardCharsets.UTF_8));
throw new DaprException("UNKNOWN", new String(json, StandardCharsets.UTF_8), json);
}
}

Expand Down Expand Up @@ -383,18 +382,19 @@ public void onFailure(Call call, IOException e) {
public void onResponse(@NotNull Call call, @NotNull okhttp3.Response response) throws IOException {
if (!response.isSuccessful()) {
try {
DaprError error = parseDaprError(getBodyBytesOrEmptyArray(response));
byte[] payload = getBodyBytesOrEmptyArray(response);
DaprError error = parseDaprError(payload);
if ((error != null) && (error.getErrorCode() != null)) {
if (error.getMessage() != null) {
future.completeExceptionally(new DaprException(error));
future.completeExceptionally(new DaprException(error, payload));
} else {
future.completeExceptionally(
new DaprException(error.getErrorCode(), "HTTP status code: " + response.code()));
new DaprException(error.getErrorCode(), "HTTP status code: " + response.code(), payload));
}
return;
}

future.completeExceptionally(new DaprException("UNKNOWN", "HTTP status code: " + response.code()));
future.completeExceptionally(new DaprException("UNKNOWN", "HTTP status code: " + response.code(), payload));
return;
} catch (DaprException e) {
future.completeExceptionally(e);
Expand Down
49 changes: 39 additions & 10 deletions sdk/src/main/java/io/dapr/exceptions/DaprException.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ public class DaprException extends RuntimeException {
*/
private DaprErrorDetails errorDetails;

/**
* Optional payload, if the exception came from a response body.
*/
private byte[] payload;

/**
* New exception from a server-side generated error code and message.
*
* @param daprError Server-side error.
* @param payload Payload containing the error.
*/
public DaprException(DaprError daprError) {
this(daprError.getErrorCode(), daprError.getMessage(), daprError.getDetails());
public DaprException(DaprError daprError, byte[] payload) {
this(daprError.getErrorCode(), daprError.getMessage(), daprError.getDetails(), payload);
}

/**
Expand Down Expand Up @@ -71,9 +77,10 @@ public DaprException(Throwable exception) {
*
* @param errorCode Client-side error code.
* @param message Client-side error message.
* @param payload Error's raw payload.
*/
public DaprException(String errorCode, String message) {
this(errorCode, message, DaprErrorDetails.EMPTY_INSTANCE);
public DaprException(String errorCode, String message, byte[] payload) {
this(errorCode, message, DaprErrorDetails.EMPTY_INSTANCE, payload);
}

/**
Expand All @@ -82,9 +89,10 @@ public DaprException(String errorCode, String message) {
* @param errorCode Client-side error code.
* @param message Client-side error message.
* @param errorDetails Details of the error from runtime.
* @param payload Payload containing the error.
*/
public DaprException(String errorCode, String message, List<Map<String, Object>> errorDetails) {
this(errorCode, message, new DaprErrorDetails(errorDetails));
public DaprException(String errorCode, String message, List<Map<String, Object>> errorDetails, byte[] payload) {
this(errorCode, message, new DaprErrorDetails(errorDetails), payload);
}

/**
Expand All @@ -93,11 +101,13 @@ public DaprException(String errorCode, String message, List<Map<String, Object>>
* @param errorCode Client-side error code.
* @param message Client-side error message.
* @param errorDetails Details of the error from runtime.
* @param payload Payload containing the error.
*/
public DaprException(String errorCode, String message, DaprErrorDetails errorDetails) {
public DaprException(String errorCode, String message, DaprErrorDetails errorDetails, byte[] payload) {
super(String.format("%s: %s", errorCode, message));
this.errorCode = errorCode;
this.errorDetails = errorDetails;
this.payload = payload;
}

/**
Expand All @@ -123,11 +133,14 @@ public DaprException(String errorCode, String message, Throwable cause) {
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @param errorDetails the status details for the error.
* @param payload Raw error payload.
*/
public DaprException(String errorCode, String message, Throwable cause, DaprErrorDetails errorDetails) {
public DaprException(
String errorCode, String message, Throwable cause, DaprErrorDetails errorDetails, byte[] payload) {
super(String.format("%s: %s", errorCode, emptyIfNull(message)), cause);
this.errorCode = errorCode;
this.errorDetails = errorDetails == null ? DaprErrorDetails.EMPTY_INSTANCE : errorDetails;
this.payload = payload;
}

/**
Expand All @@ -139,10 +152,24 @@ public String getErrorCode() {
return this.errorCode;
}

public DaprErrorDetails getStatusDetails() {
/**
* Returns the exception's error details.
*
* @return Error details.
*/
public DaprErrorDetails getErrorDetails() {
return this.errorDetails;
}

/**
* Returns the exception's error payload (optional).
*
* @return Error's payload.
*/
public byte[] getPayload() {
return this.payload == null ? null : this.payload.clone();
}

/**
* Wraps an exception into DaprException (if not already DaprException).
*
Expand Down Expand Up @@ -247,7 +274,9 @@ public static RuntimeException propagate(Throwable exception) {
statusRuntimeException.getStatus().getCode().toString(),
statusRuntimeException.getStatus().getDescription(),
exception,
errorDetails);
errorDetails,
status.toByteArray());

}

e = e.getCause();
Expand Down
1 change: 1 addition & 0 deletions sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ public void invokeServiceDaprErrorUnknownJSON() {

assertEquals("UNKNOWN", exception.getErrorCode());
assertEquals("UNKNOWN: { \"anything\": 7 }", exception.getMessage());
assertEquals("{ \"anything\": 7 }", new String(exception.getPayload()));
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/test/java/io/dapr/client/DaprHttpTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void validateExceptionParsing() {
DaprException daprException = (DaprException)e;
assertEquals("ERR_PUBSUB_NOT_FOUND", daprException.getErrorCode());
assertEquals("DAPR_PUBSUB_NOT_FOUND",
daprException.getStatusDetails()
daprException.getErrorDetails()
.get(DaprErrorDetails.ErrorDetailType.ERROR_INFO, "reason", TypeRef.STRING));
return true;
}).verify();
Expand Down
3 changes: 1 addition & 2 deletions sdk/src/test/java/io/dapr/utils/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import java.io.IOException;
import java.net.ServerSocket;
import java.util.Map;

public final class TestUtils {

Expand Down Expand Up @@ -71,7 +70,7 @@ public static <T extends Throwable> void assertThrowsDaprException(
Assertions.assertEquals(expectedType, daprException.getCause().getClass());
Assertions.assertEquals(expectedErrorCode, daprException.getErrorCode());
Assertions.assertEquals(expectedErrorMessage, daprException.getMessage());
Assertions.assertEquals(expectedStatusDetails, daprException.getStatusDetails());
Assertions.assertEquals(expectedStatusDetails, daprException.getErrorDetails());
}

public static int findFreePort() throws IOException {
Expand Down

0 comments on commit 81e6c4d

Please sign in to comment.