Skip to content

Commit 593da48

Browse files
Catering to all possible routes for Post Request (#700)
* Catering to all possible routes for Post Request Signed-off-by: deepanshuagarwal <[email protected]> * Correcting checkstyle related violations Signed-off-by: deepanshuagarwal <[email protected]> * Refactoring and Adding UTs for post method routes Signed-off-by: deepanshuagarwal <[email protected]> * Using resolved topic name Signed-off-by: deepanshuagarwal <[email protected]> * Shifting routesPostMethod to reduce its access Signed-off-by: deepanshuagarwal <[email protected]> Co-authored-by: Mukundan Sundararajan <[email protected]>
1 parent 06d92da commit 593da48

5 files changed

Lines changed: 227 additions & 10 deletions

File tree

sdk-springboot/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@
8888
<scope>compile</scope>
8989
<optional>true</optional>
9090
</dependency>
91+
<dependency>
92+
<groupId>junit</groupId>
93+
<artifactId>junit</artifactId>
94+
<scope>test</scope>
95+
</dependency>
9196
</dependencies>
9297

9398
<build>
@@ -149,6 +154,9 @@
149154
<rules>
150155
<rule>
151156
<element>BUNDLE</element>
157+
<includes>
158+
<include>io.dapr.springboot.DaprBeanPostProcessor</include>
159+
</includes>
152160
<limits>
153161
<limit>
154162
<counter>LINE</counter>

sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@
2323
import org.springframework.beans.factory.config.EmbeddedValueResolver;
2424
import org.springframework.stereotype.Component;
2525
import org.springframework.web.bind.annotation.PostMapping;
26+
import org.springframework.web.bind.annotation.RequestMapping;
27+
import org.springframework.web.bind.annotation.RequestMethod;
2628

29+
import java.lang.annotation.Annotation;
2730
import java.lang.reflect.Method;
31+
import java.util.ArrayList;
2832
import java.util.HashMap;
33+
import java.util.List;
2934
import java.util.Map;
3035

3136
/**
@@ -80,27 +85,91 @@ private static void subscribeToTopics(Class clazz, EmbeddedValueResolver embedde
8085
continue;
8186
}
8287

83-
String route = topic.name();
84-
PostMapping mapping = method.getAnnotation(PostMapping.class);
85-
86-
if (mapping != null && mapping.path() != null && mapping.path().length >= 1) {
87-
route = mapping.path()[0];
88-
} else if (mapping != null && mapping.value() != null && mapping.value().length >= 1) {
89-
route = mapping.value()[0];
90-
}
91-
9288
String topicName = embeddedValueResolver.resolveStringValue(topic.name());
9389
String pubSubName = embeddedValueResolver.resolveStringValue(topic.pubsubName());
9490
if ((topicName != null) && (topicName.length() > 0) && pubSubName != null && pubSubName.length() > 0) {
9591
try {
9692
TypeReference<HashMap<String, String>> typeRef
9793
= new TypeReference<HashMap<String, String>>() {};
9894
Map<String, String> metadata = MAPPER.readValue(topic.metadata(), typeRef);
99-
DaprRuntime.getInstance().addSubscribedTopic(pubSubName, topicName, route, metadata);
95+
List<String> routes = getAllCompleteRoutesForPost(clazz, method, topicName);
96+
for (String route : routes) {
97+
DaprRuntime.getInstance().addSubscribedTopic(pubSubName, topicName, route,
98+
metadata);
99+
}
100+
100101
} catch (JsonProcessingException e) {
101102
throw new IllegalArgumentException("Error while parsing metadata: " + e.toString());
102103
}
103104
}
104105
}
105106
}
107+
108+
/**
109+
* Method to provide all possible complete routes list fos this post method present in this controller class,
110+
* for mentioned topic.
111+
*
112+
* @param clazz Controller class
113+
* @param method Declared method for posting data
114+
* @param topicName Associated topic name
115+
* @return All possible routes for post mapping for this class and post method
116+
*/
117+
private static List<String> getAllCompleteRoutesForPost(Class clazz, Method method, String topicName) {
118+
List<String> routesList = new ArrayList<>();
119+
RequestMapping clazzRequestMapping =
120+
(RequestMapping) clazz.getAnnotation(RequestMapping.class);
121+
String[] clazzLevelRoute = null;
122+
if (clazzRequestMapping != null) {
123+
clazzLevelRoute = clazzRequestMapping.value();
124+
}
125+
String[] postValueArray = getRoutesForPost(method, topicName);
126+
if (postValueArray != null && postValueArray.length >= 1) {
127+
for (String postValue : postValueArray) {
128+
if (clazzLevelRoute != null && clazzLevelRoute.length >= 1) {
129+
for (String clazzLevelValue : clazzLevelRoute) {
130+
String route = clazzLevelValue + confirmLeadingSlash(postValue);
131+
routesList.add(route);
132+
}
133+
} else {
134+
routesList.add(postValue);
135+
}
136+
}
137+
}
138+
return routesList;
139+
}
140+
141+
private static String[] getRoutesForPost(Method method, String topicName) {
142+
String[] postValueArray = new String[] {topicName};
143+
PostMapping postMapping = method.getAnnotation(PostMapping.class);
144+
if (postMapping != null) {
145+
if (postMapping.path() != null && postMapping.path().length >= 1) {
146+
postValueArray = postMapping.path();
147+
} else if (postMapping.value() != null && postMapping.value().length >= 1) {
148+
postValueArray = postMapping.value();
149+
}
150+
} else {
151+
RequestMapping reqMapping = method.getAnnotation(RequestMapping.class);
152+
for (RequestMethod reqMethod : reqMapping.method()) {
153+
if (reqMethod == RequestMethod.POST) {
154+
if (reqMapping.path() != null && reqMapping.path().length >= 1) {
155+
postValueArray = reqMapping.path();
156+
} else if (reqMapping.value() != null && reqMapping.value().length >= 1) {
157+
postValueArray = reqMapping.value();
158+
}
159+
break;
160+
}
161+
}
162+
}
163+
return postValueArray;
164+
}
165+
166+
private static String confirmLeadingSlash(String path) {
167+
if (path != null && path.length() >= 1) {
168+
if (!path.substring(0, 1).equals("/")) {
169+
return "/" + path;
170+
}
171+
}
172+
return path;
173+
}
174+
106175
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.dapr.springboot;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
import org.junit.runner.RunWith;
6+
import org.junit.runners.Parameterized;
7+
8+
import java.lang.reflect.InvocationTargetException;
9+
import java.lang.reflect.Method;
10+
import java.util.Arrays;
11+
import java.util.Collection;
12+
import java.util.List;
13+
14+
@RunWith(Parameterized.class)
15+
public class DaprBeanPostProcessorTest {
16+
17+
private final Class<?> clazzToBeTested;
18+
private final String methodToBeTested;
19+
private final String[] expected;
20+
private final boolean expectedResult;
21+
private static final String TOPIC_NAME = "topicName1";
22+
23+
public DaprBeanPostProcessorTest(Class<?> clazzToBeTested, String methodToBeTested, String[] expected,
24+
boolean expectedResult) {
25+
this.clazzToBeTested = clazzToBeTested;
26+
this.methodToBeTested = methodToBeTested;
27+
this.expected = expected;
28+
this.expectedResult = expectedResult;
29+
}
30+
31+
@Parameterized.Parameters
32+
public static Collection<?> routesTester() {
33+
return Arrays.asList(new Object[][] {
34+
{MockController.class, "testMethod1", new String[] {"v1", "v2", "v1/page1", "v2/page1", "v1/page2", "v2/page2"},
35+
true},
36+
{MockController.class, "testMethod2", new String[] {"v1", "v2", "v1/page3", "v2/page3", "v1/page4", "v2/page4"},
37+
true},
38+
{MockController.class, "testMethod3", new String[] {"v1/foo", "v2/foo"}, true},
39+
{MockController.class, "testMethod4", new String[] {"v1/foo1", "v2/foo1", "v1/foo2", "v2/foo2"}, true},
40+
{MockController.class, "testMethod5", new String[] {"v1/" + TOPIC_NAME, "v2/" + TOPIC_NAME}, true},
41+
{MockControllerNoClazzAnnotation.class, "testMethod1", new String[] {"", "page1", "page2"}, true},
42+
{MockControllerNoClazzAnnotation.class, "testMethod2", new String[] {"", "page3", "page4"}, true},
43+
{MockControllerNoClazzAnnotation.class, "testMethod3", new String[] {"foo"}, true},
44+
{MockControllerNoClazzAnnotation.class, "testMethod4", new String[] {"foo1", "foo2"}, true},
45+
{MockControllerNoClazzAnnotation.class, "testMethod5", new String[] {TOPIC_NAME}, true}
46+
});
47+
}
48+
49+
@Test
50+
public void testAllPostRoutesGeneration() throws NoSuchMethodException {
51+
Method allPostRoutesMethod = DaprBeanPostProcessor.class.
52+
getDeclaredMethod("getAllCompleteRoutesForPost", Class.class, Method.class, String.class);
53+
allPostRoutesMethod.setAccessible(true);
54+
List<String> routesArrayTestMethod1 = null;
55+
try {
56+
routesArrayTestMethod1 = (List<String>) allPostRoutesMethod.invoke(DaprBeanPostProcessor.class, clazzToBeTested,
57+
clazzToBeTested.getMethod(methodToBeTested), TOPIC_NAME);
58+
} catch (IllegalAccessException | InvocationTargetException e) {
59+
e.printStackTrace();
60+
}
61+
Assert.assertEquals(expectedResult,
62+
testingListForOrderAgnosticEquality(Arrays.asList(expected), routesArrayTestMethod1));
63+
}
64+
65+
private boolean testingListForOrderAgnosticEquality(List<?> first, List<?> second) {
66+
return (first.size() == second.size() && first.containsAll(second) && second.containsAll(first));
67+
}
68+
69+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.dapr.springboot;
2+
3+
import org.springframework.web.bind.annotation.*;
4+
5+
@RequestMapping(value = {"v1", "v2"})
6+
public class MockController {
7+
8+
@RequestMapping(value = {"", "/page1", "page2"}, method = {RequestMethod.POST, RequestMethod.PUT})
9+
public void testMethod1() {
10+
// Do nothing
11+
}
12+
13+
@PostMapping(path = {"", "/page3", "page4"})
14+
public void testMethod2() {
15+
// Do nothing
16+
}
17+
18+
@PostMapping("foo")
19+
public void testMethod3() {
20+
// Do nothing
21+
}
22+
23+
@PostMapping({"/foo1", "foo2"})
24+
public void testMethod4() {
25+
// Do nothing
26+
}
27+
28+
29+
@RequestMapping(path = {"/bar", "bar1"}, method = {RequestMethod.GET})
30+
public void testMethod5() {
31+
// Do nothing
32+
}
33+
34+
35+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.dapr.springboot;
2+
3+
import org.springframework.web.bind.annotation.PostMapping;
4+
import org.springframework.web.bind.annotation.RequestMapping;
5+
import org.springframework.web.bind.annotation.RequestMethod;
6+
7+
public class MockControllerNoClazzAnnotation {
8+
9+
@RequestMapping(value = {"", "page1", "page2"}, method = {RequestMethod.POST, RequestMethod.PUT})
10+
public void testMethod1() {
11+
// Do nothing
12+
}
13+
14+
@PostMapping(path = {"", "page3", "page4"})
15+
public void testMethod2() {
16+
// Do nothing
17+
}
18+
19+
@PostMapping("foo")
20+
public void testMethod3() {
21+
// Do nothing
22+
}
23+
24+
@PostMapping({"foo1", "foo2"})
25+
public void testMethod4() {
26+
// Do nothing
27+
}
28+
29+
30+
@RequestMapping(path = {"bar", "bar1"}, method = {RequestMethod.GET})
31+
public void testMethod5() {
32+
// Do nothing
33+
}
34+
35+
36+
}

0 commit comments

Comments
 (0)