Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions sdk-springboot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -149,6 +154,9 @@
<rules>
<rule>
<element>BUNDLE</element>
<includes>
<include>io.dapr.springboot.DaprBeanPostProcessor</include>
</includes>
<limits>
<limit>
<counter>LINE</counter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@
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;

/**
Expand Down Expand Up @@ -80,27 +85,91 @@ private static void subscribeToTopics(Class clazz, EmbeddedValueResolver embedde
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) {
try {
TypeReference<HashMap<String, String>> typeRef
= new TypeReference<HashMap<String, String>>() {};
Map<String, String> metadata = MAPPER.readValue(topic.metadata(), typeRef);
DaprRuntime.getInstance().addSubscribedTopic(pubSubName, topicName, route, metadata);
List<String> 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<String> getAllCompleteRoutesForPost(Class clazz, Method method, String topicName) {
List<String> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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<String> routesArrayTestMethod1 = null;
try {
routesArrayTestMethod1 = (List<String>) 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));
}

}
Original file line number Diff line number Diff line change
@@ -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
}


}
Original file line number Diff line number Diff line change
@@ -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
}


}