diff --git a/sdk-springboot/pom.xml b/sdk-springboot/pom.xml
index 042c06580..cd6b2df50 100644
--- a/sdk-springboot/pom.xml
+++ b/sdk-springboot/pom.xml
@@ -88,6 +88,11 @@
compile
true
+
+ junit
+ junit
+ test
+
@@ -149,6 +154,9 @@
BUNDLE
+
+ io.dapr.springboot.DaprBeanPostProcessor
+
LINE
diff --git a/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java b/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java
index 56cae1b29..cc591184a 100644
--- a/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java
+++ b/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java
@@ -23,9 +23,14 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -80,15 +85,6 @@ public class DaprBeanPostProcessor implements BeanPostProcessor {
continue;
}
- String route = topic.name();
- PostMapping mapping = method.getAnnotation(PostMapping.class);
-
- if (mapping != null && mapping.path() != null && mapping.path().length >= 1) {
- route = mapping.path()[0];
- } else if (mapping != null && mapping.value() != null && mapping.value().length >= 1) {
- route = mapping.value()[0];
- }
-
String topicName = embeddedValueResolver.resolveStringValue(topic.name());
String pubSubName = embeddedValueResolver.resolveStringValue(topic.pubsubName());
if ((topicName != null) && (topicName.length() > 0) && pubSubName != null && pubSubName.length() > 0) {
@@ -96,11 +92,84 @@ public class DaprBeanPostProcessor implements BeanPostProcessor {
TypeReference> typeRef
= new TypeReference>() {};
Map metadata = MAPPER.readValue(topic.metadata(), typeRef);
- DaprRuntime.getInstance().addSubscribedTopic(pubSubName, topicName, route, metadata);
+ List routes = getAllCompleteRoutesForPost(clazz, method, topicName);
+ for (String route : routes) {
+ DaprRuntime.getInstance().addSubscribedTopic(pubSubName, topicName, route,
+ metadata);
+ }
+
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Error while parsing metadata: " + e.toString());
}
}
}
}
+
+ /**
+ * Method to provide all possible complete routes list fos this post method present in this controller class,
+ * for mentioned topic.
+ *
+ * @param clazz Controller class
+ * @param method Declared method for posting data
+ * @param topicName Associated topic name
+ * @return All possible routes for post mapping for this class and post method
+ */
+ private static List getAllCompleteRoutesForPost(Class clazz, Method method, String topicName) {
+ List routesList = new ArrayList<>();
+ RequestMapping clazzRequestMapping =
+ (RequestMapping) clazz.getAnnotation(RequestMapping.class);
+ String[] clazzLevelRoute = null;
+ if (clazzRequestMapping != null) {
+ clazzLevelRoute = clazzRequestMapping.value();
+ }
+ String[] postValueArray = getRoutesForPost(method, topicName);
+ if (postValueArray != null && postValueArray.length >= 1) {
+ for (String postValue : postValueArray) {
+ if (clazzLevelRoute != null && clazzLevelRoute.length >= 1) {
+ for (String clazzLevelValue : clazzLevelRoute) {
+ String route = clazzLevelValue + confirmLeadingSlash(postValue);
+ routesList.add(route);
+ }
+ } else {
+ routesList.add(postValue);
+ }
+ }
+ }
+ return routesList;
+ }
+
+ private static String[] getRoutesForPost(Method method, String topicName) {
+ String[] postValueArray = new String[] {topicName};
+ PostMapping postMapping = method.getAnnotation(PostMapping.class);
+ if (postMapping != null) {
+ if (postMapping.path() != null && postMapping.path().length >= 1) {
+ postValueArray = postMapping.path();
+ } else if (postMapping.value() != null && postMapping.value().length >= 1) {
+ postValueArray = postMapping.value();
+ }
+ } else {
+ RequestMapping reqMapping = method.getAnnotation(RequestMapping.class);
+ for (RequestMethod reqMethod : reqMapping.method()) {
+ if (reqMethod == RequestMethod.POST) {
+ if (reqMapping.path() != null && reqMapping.path().length >= 1) {
+ postValueArray = reqMapping.path();
+ } else if (reqMapping.value() != null && reqMapping.value().length >= 1) {
+ postValueArray = reqMapping.value();
+ }
+ break;
+ }
+ }
+ }
+ return postValueArray;
+ }
+
+ private static String confirmLeadingSlash(String path) {
+ if (path != null && path.length() >= 1) {
+ if (!path.substring(0, 1).equals("/")) {
+ return "/" + path;
+ }
+ }
+ return path;
+ }
+
}
diff --git a/sdk-springboot/src/test/java/io/dapr/springboot/DaprBeanPostProcessorTest.java b/sdk-springboot/src/test/java/io/dapr/springboot/DaprBeanPostProcessorTest.java
new file mode 100644
index 000000000..403d5e21c
--- /dev/null
+++ b/sdk-springboot/src/test/java/io/dapr/springboot/DaprBeanPostProcessorTest.java
@@ -0,0 +1,69 @@
+package io.dapr.springboot;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@RunWith(Parameterized.class)
+public class DaprBeanPostProcessorTest {
+
+ private final Class> clazzToBeTested;
+ private final String methodToBeTested;
+ private final String[] expected;
+ private final boolean expectedResult;
+ private static final String TOPIC_NAME = "topicName1";
+
+ public DaprBeanPostProcessorTest(Class> clazzToBeTested, String methodToBeTested, String[] expected,
+ boolean expectedResult) {
+ this.clazzToBeTested = clazzToBeTested;
+ this.methodToBeTested = methodToBeTested;
+ this.expected = expected;
+ this.expectedResult = expectedResult;
+ }
+
+ @Parameterized.Parameters
+ public static Collection> routesTester() {
+ return Arrays.asList(new Object[][] {
+ {MockController.class, "testMethod1", new String[] {"v1", "v2", "v1/page1", "v2/page1", "v1/page2", "v2/page2"},
+ true},
+ {MockController.class, "testMethod2", new String[] {"v1", "v2", "v1/page3", "v2/page3", "v1/page4", "v2/page4"},
+ true},
+ {MockController.class, "testMethod3", new String[] {"v1/foo", "v2/foo"}, true},
+ {MockController.class, "testMethod4", new String[] {"v1/foo1", "v2/foo1", "v1/foo2", "v2/foo2"}, true},
+ {MockController.class, "testMethod5", new String[] {"v1/" + TOPIC_NAME, "v2/" + TOPIC_NAME}, true},
+ {MockControllerNoClazzAnnotation.class, "testMethod1", new String[] {"", "page1", "page2"}, true},
+ {MockControllerNoClazzAnnotation.class, "testMethod2", new String[] {"", "page3", "page4"}, true},
+ {MockControllerNoClazzAnnotation.class, "testMethod3", new String[] {"foo"}, true},
+ {MockControllerNoClazzAnnotation.class, "testMethod4", new String[] {"foo1", "foo2"}, true},
+ {MockControllerNoClazzAnnotation.class, "testMethod5", new String[] {TOPIC_NAME}, true}
+ });
+ }
+
+ @Test
+ public void testAllPostRoutesGeneration() throws NoSuchMethodException {
+ Method allPostRoutesMethod = DaprBeanPostProcessor.class.
+ getDeclaredMethod("getAllCompleteRoutesForPost", Class.class, Method.class, String.class);
+ allPostRoutesMethod.setAccessible(true);
+ List routesArrayTestMethod1 = null;
+ try {
+ routesArrayTestMethod1 = (List) allPostRoutesMethod.invoke(DaprBeanPostProcessor.class, clazzToBeTested,
+ clazzToBeTested.getMethod(methodToBeTested), TOPIC_NAME);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ Assert.assertEquals(expectedResult,
+ testingListForOrderAgnosticEquality(Arrays.asList(expected), routesArrayTestMethod1));
+ }
+
+ private boolean testingListForOrderAgnosticEquality(List> first, List> second) {
+ return (first.size() == second.size() && first.containsAll(second) && second.containsAll(first));
+ }
+
+}
diff --git a/sdk-springboot/src/test/java/io/dapr/springboot/MockController.java b/sdk-springboot/src/test/java/io/dapr/springboot/MockController.java
new file mode 100644
index 000000000..ee32c15cd
--- /dev/null
+++ b/sdk-springboot/src/test/java/io/dapr/springboot/MockController.java
@@ -0,0 +1,35 @@
+package io.dapr.springboot;
+
+import org.springframework.web.bind.annotation.*;
+
+@RequestMapping(value = {"v1", "v2"})
+public class MockController {
+
+ @RequestMapping(value = {"", "/page1", "page2"}, method = {RequestMethod.POST, RequestMethod.PUT})
+ public void testMethod1() {
+ // Do nothing
+ }
+
+ @PostMapping(path = {"", "/page3", "page4"})
+ public void testMethod2() {
+ // Do nothing
+ }
+
+ @PostMapping("foo")
+ public void testMethod3() {
+ // Do nothing
+ }
+
+ @PostMapping({"/foo1", "foo2"})
+ public void testMethod4() {
+ // Do nothing
+ }
+
+
+ @RequestMapping(path = {"/bar", "bar1"}, method = {RequestMethod.GET})
+ public void testMethod5() {
+ // Do nothing
+ }
+
+
+}
\ No newline at end of file
diff --git a/sdk-springboot/src/test/java/io/dapr/springboot/MockControllerNoClazzAnnotation.java b/sdk-springboot/src/test/java/io/dapr/springboot/MockControllerNoClazzAnnotation.java
new file mode 100644
index 000000000..1a64920db
--- /dev/null
+++ b/sdk-springboot/src/test/java/io/dapr/springboot/MockControllerNoClazzAnnotation.java
@@ -0,0 +1,36 @@
+package io.dapr.springboot;
+
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+public class MockControllerNoClazzAnnotation {
+
+ @RequestMapping(value = {"", "page1", "page2"}, method = {RequestMethod.POST, RequestMethod.PUT})
+ public void testMethod1() {
+ // Do nothing
+ }
+
+ @PostMapping(path = {"", "page3", "page4"})
+ public void testMethod2() {
+ // Do nothing
+ }
+
+ @PostMapping("foo")
+ public void testMethod3() {
+ // Do nothing
+ }
+
+ @PostMapping({"foo1", "foo2"})
+ public void testMethod4() {
+ // Do nothing
+ }
+
+
+ @RequestMapping(path = {"bar", "bar1"}, method = {RequestMethod.GET})
+ public void testMethod5() {
+ // Do nothing
+ }
+
+
+}
\ No newline at end of file