Skip to content

Commit 8f860b9

Browse files
authored
fix<data converter>: fail open on exception not found (#1027)
What changed? Default data converter would throw I/O exception and thus fail workflow processing if the exception no longer exists. This PR changes the behavior by return null instead. Why? In V4, thrift exceptions will be removed and thus this is needed to avoid breaking existing workflows. How did you test it? Unit Test
1 parent 8bb6468 commit 8f860b9

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* <p>Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* <p>Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file
7+
* except in compliance with the License. A copy of the License is located at
8+
*
9+
* <p>http://aws.amazon.com/apache2.0
10+
*
11+
* <p>or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+
* specific language governing permissions and limitations under the License.
14+
*/
15+
package com.uber.cadence.client;
16+
17+
import com.uber.cadence.CadenceError;
18+
19+
public final class ApplicationFailureException extends CadenceError {
20+
21+
public ApplicationFailureException(String message) {
22+
super(message);
23+
}
24+
}

src/main/java/com/uber/cadence/converter/CustomThrowableTypeAdapter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.gson.reflect.TypeToken;
2323
import com.google.gson.stream.JsonReader;
2424
import com.google.gson.stream.JsonWriter;
25+
import com.uber.cadence.client.ApplicationFailureException;
2526
import java.io.IOException;
2627
import java.io.PrintWriter;
2728
import java.io.StringWriter;
@@ -137,7 +138,7 @@ public T read(JsonReader jsonReader) throws IOException {
137138
try {
138139
classType = Class.forName(className);
139140
} catch (ClassNotFoundException e) {
140-
throw new IOException("Cannot deserialize " + className + " exception", e);
141+
classType = ApplicationFailureException.class;
141142
}
142143
if (!Throwable.class.isAssignableFrom(classType)) {
143144
throw new IOException("Expected type that extends Throwable: " + className);

src/test/java/com/uber/cadence/converter/JsonDataConverterTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.uber.cadence.WorkflowExecutionStartedEventAttributes;
2828
import com.uber.cadence.WorkflowType;
2929
import com.uber.cadence.activity.Activity;
30+
import com.uber.cadence.client.ApplicationFailureException;
3031
import java.io.File;
3132
import java.io.FileInputStream;
3233
import java.io.IOException;
@@ -270,4 +271,23 @@ public void testException() {
270271

271272
assertEquals("root exception", causeFromConverted.getSuppressed()[0].getMessage());
272273
}
274+
275+
@Test
276+
public void testExceptionNotFound() {
277+
String convertedString =
278+
"{\n"
279+
+ " \"detailMessage\": \"application exception\",\n"
280+
+ " \"stackTrace\": \"com.uber.cadence.converter.JsonDataConverterTest.testExceptionNotFound(JsonDataConverterTest.java:282)\\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\\nsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\\njava.lang.reflect.Method.invoke(Method.java:498)\\norg.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)\\norg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\\norg.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)\\norg.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\\norg.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\\norg.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)\\norg.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)\\norg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)\\norg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)\\norg.junit.runners.ParentRunner$4.run(ParentRunner.java:331)\\norg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)\\norg.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)\\norg.junit.runners.ParentRunner.access$100(ParentRunner.java:66)\\norg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)\\norg.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\\norg.junit.runners.ParentRunner.run(ParentRunner.java:413)\\norg.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)\\norg.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)\\norg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:520)\\norg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:748)\\norg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:443)\\norg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)\\n\",\n"
281+
+ " \"suppressedExceptions\": [],\n"
282+
+ " \"class\": \"com.uber.cadence.converter.ExceptionNotFound\"\n"
283+
+ "}";
284+
RuntimeException fromConverted =
285+
converter.fromData(
286+
convertedString.getBytes(StandardCharsets.UTF_8),
287+
RuntimeException.class,
288+
RuntimeException.class);
289+
assertEquals(ApplicationFailureException.class, fromConverted.getClass());
290+
assertEquals("application exception", fromConverted.getMessage());
291+
assertNotSame(fromConverted.getStackTrace().length, 0);
292+
}
273293
}

0 commit comments

Comments
 (0)