diff --git a/ReleaseNotes.md b/ReleaseNotes.md index ed7fa5f4..1c6bc22a 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -10,6 +10,7 @@ * IBS.DESERIALIZATION.DEPTH.LIMIT : This value sets the maximum depth of the deserialization. * IBS.DESERIALIZATION.DATE.FORMAT : The format in which the date should be deserialized. * IBS.PLUGINS.PACKAGE : The package path in which the IBS should search for the plugins you write. +* [#176 ClassCastException when the second call argument is an array](https://github.com/adobe/bridgeService/issues/176). We discovered a bug regarding arrays. Whenever the second argument was an array, we would get a ClassCastException. ## 2.11.16 * **New Feature** [#3 Include an Assertion Feature](https://github.com/adobe/bridgeService/issues/3). We have now included the possibility for users to define assertions. This allows you to clarify accepted results for the call you make with the IBS. diff --git a/bridgeService-data/src/main/java/com/adobe/campaign/tests/bridge/testdata/one/SimpleStaticMethods.java b/bridgeService-data/src/main/java/com/adobe/campaign/tests/bridge/testdata/one/SimpleStaticMethods.java index 7ff8109a..8e31ef97 100644 --- a/bridgeService-data/src/main/java/com/adobe/campaign/tests/bridge/testdata/one/SimpleStaticMethods.java +++ b/bridgeService-data/src/main/java/com/adobe/campaign/tests/bridge/testdata/one/SimpleStaticMethods.java @@ -124,4 +124,10 @@ public static void methodCallingMethodThrowingExceptionAndPackingIt() { public static String methodAcceptingFile(File fileObject) throws IOException { return Files.readString(fileObject.toPath(), StandardCharsets.UTF_8); } + + //Issue #176 + public int methodAcceptingStringAndArray(String stringObject, String[] arrayObject) { + return stringObject.length()+arrayObject.length; + } + } diff --git a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/CallContent.java b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/CallContent.java index ea73c3f1..a2461f78 100644 --- a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/CallContent.java +++ b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/CallContent.java @@ -260,20 +260,24 @@ public int hashCode() { return result; } + + /** * This method transforms the arguments, when necessary to the target objects - * @param in_objects - * @param in_method - * @return + * @param in_objects An array of argument objects + * @param in_method The method we want to call + * @return The transformed array of objects for execution purposes. */ - Object[] castArgs(Object[] in_objects, Method in_method) { + Object[] castArgs(Object[] in_objects, Method in_method) { List ltr_objects = new ArrayList<>(); for (int i=0; i < in_objects.length; i++) { Class lt_type = in_method.getParameterTypes()[i]; + + //If object is an array if (lt_type.isArray() && in_objects[i] instanceof List) { Class lt_targetClass = lt_type.getComponentType(); - Object lt_targetObject = Array.newInstance(lt_targetClass, ((List)in_objects[0]).size()); - for (int i2=0; i2 < ((List)in_objects[0]).size(); i2++) { + Object lt_targetObject = Array.newInstance(lt_targetClass, ((List)in_objects[i]).size()); + for (int i2=0; i2 < ((List)in_objects[i]).size(); i2++) { Array.set(lt_targetObject, i2, ((List) in_objects[i]).get(i2)); } ltr_objects.add(lt_targetObject); @@ -284,4 +288,5 @@ Object[] castArgs(Object[] in_objects, Method in_method) { return ltr_objects.toArray(); } + } diff --git a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/JavaCalls.java b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/JavaCalls.java index bb041a30..f5a0d3d3 100644 --- a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/JavaCalls.java +++ b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/JavaCalls.java @@ -77,7 +77,7 @@ public Object call(String in_key) { throw new JavaObjectInaccessibleException(e.getCause().getMessage(), e.getCause().getCause()); } else { - throw new IBSRunTimeException(e.getMessage()); + throw new IBSRunTimeException(e.getMessage(), e.getCause()); } } catch (TimeoutException e) { diff --git a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/exceptions/IBSRunTimeException.java b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/exceptions/IBSRunTimeException.java index c9cb717a..5452d1d9 100644 --- a/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/exceptions/IBSRunTimeException.java +++ b/integroBridgeService/src/main/java/com/adobe/campaign/tests/bridge/service/exceptions/IBSRunTimeException.java @@ -19,4 +19,8 @@ public class IBSRunTimeException extends RuntimeException { public IBSRunTimeException(String message) { super(message); } + + public IBSRunTimeException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/E2ETests.java b/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/E2ETests.java index c8d8fc9c..aac36ba6 100644 --- a/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/E2ETests.java +++ b/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/E2ETests.java @@ -956,6 +956,25 @@ public void testCallWithFileUpload_negativeNoIBSPayload() throws IOException { } + + @Test(groups = "E2E") + public void testIssue176_classCastExceptionArrayFollowingString() throws IOException { + + JavaCalls l_myJavaCall = new JavaCalls(); + + CallContent l_cc1 = new CallContent(); + l_cc1.setClassName(SimpleStaticMethods.class.getTypeName()); + l_cc1.setMethodName("methodAcceptingStringAndArray"); + String[] l_array = new String[]{"value1", "value2"}; + l_cc1.setArgs(new Object[]{"ASD", l_array}); + + l_myJavaCall.getCallContent().put("fetchResults", l_cc1); + + given().body(l_myJavaCall).post(EndPointURL + "call").then().assertThat().statusCode(200).body("returnValues.fetchResults", + Matchers.equalTo(5)); + } + + @AfterGroups(groups = "E2E", alwaysRun = true) public void tearDown() throws IOException { diff --git a/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/TestFetchCalls.java b/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/TestFetchCalls.java index 19a8f5fa..44456aae 100644 --- a/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/TestFetchCalls.java +++ b/integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/service/TestFetchCalls.java @@ -15,6 +15,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.hamcrest.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeMethod; @@ -1997,6 +1999,45 @@ public void testInListToArrayTransformation() throws NoSuchMethodException, Clas assertThat("We should get the correct return value", l_myJavaCall.call("call1"), Matchers.equalTo(2)); } + @Test + public void testInListToArrayTransformationBug176() throws NoSuchMethodException, ClassNotFoundException { + JavaCalls l_myJavaCall = new JavaCalls(); + + CallContent l_cc = new CallContent(); + l_cc.setClassName(SimpleStaticMethods.class.getTypeName()); + l_cc.setMethodName("methodAcceptingStringAndArray"); + List l_array = Arrays.asList("value1", "value2"); + l_cc.setArgs(new Object[]{"ASD", l_array}); + l_myJavaCall.getCallContent().put("call1", l_cc); + + Method l_myMethod = SimpleStaticMethods.class.getDeclaredMethod(l_cc.getMethodName(), String.class, String[].class); + System.out.println(l_myMethod.getParameterTypes()[0]); + System.out.println(l_myMethod.getParameterTypes()[1]); + assertThat("The second parameter is a String",l_myMethod.getParameterTypes()[0], Matchers.equalTo(String.class)); + + assertThat("The second parameter is an array",l_myMethod.getParameterTypes()[1].isArray()); + assertThat("The Second parameter is an array",l_myMethod.getParameterTypes()[1], Matchers.equalTo(String[].class)); + + System.out.println(l_myMethod.getParameterTypes()[1].getComponentType().getTypeName()); + + assertThat("We should now have an array of array", l_cc.getArgs()[0], Matchers.instanceOf(String.class)); + + System.out.println("arg "+l_cc.getArgs()[0].getClass()); + System.out.println("arg "+l_cc.getArgs()[1].getClass()); + + Object[] newArgs = l_cc.castArgs(l_cc.getArgs(), l_myMethod); + assertThat(newArgs, Matchers.notNullValue()); + assertThat("We should now have an array", newArgs[0].getClass(), Matchers.equalTo(String.class)); + + assertThat("We should now have an array", newArgs[1].getClass().isArray()); + + + assertThat("We should now have an array of Strings", newArgs[1].getClass().getComponentType(), Matchers.equalTo(String.class)); + + assertThat("We should get the correct return value", l_myJavaCall.call("call1"), Matchers.equalTo(5)); + } + + @Test public void testMetaIsListToArray() throws NoSuchMethodException { JavaCalls l_myJavaCall = new JavaCalls(); @@ -2068,5 +2109,25 @@ public void chainingComplexCallsArray() { } + @Test + public void issue176_callingMethodAcceptingStringAndArray() { + JavaCalls l_myJavaCall = new JavaCalls(); + + IntegroBridgeClassLoader iclCL = Mockito.mock(IntegroBridgeClassLoader.class); + l_myJavaCall.setLocalClassLoader(iclCL); + + Mockito.when(iclCL.getCallResultCache()).thenThrow(new RuntimeException("We should not have called this method")); + + CallContent l_cc1 = new CallContent(); + l_cc1.setClassName(SimpleStaticMethods.class.getTypeName()); + l_cc1.setMethodName("methodAcceptingStringAndArray"); + String[] l_array = new String[]{"value1", "value2"}; + l_cc1.setArgs(new Object[]{"ASD", l_array}); + + l_myJavaCall.getCallContent().put("fetchResults", l_cc1); + + Assert.assertThrows(IBSRunTimeException.class, () -> l_myJavaCall.submitCalls()); + } + }