From 731841e66f27f0bb98f37870684cf4d755633e4d Mon Sep 17 00:00:00 2001 From: Justin Rovang Date: Wed, 26 May 2021 17:39:17 -0500 Subject: [PATCH 1/6] [WIP] Added SPEL evaluation against spring boot @Topic name and pubsubname attributes --- .../dapr/springboot/DaprBeanPostProcessor.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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 22e2f4d557..9cb0c56c02 100644 --- a/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java +++ b/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java @@ -11,6 +11,8 @@ import io.dapr.Topic; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +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; @@ -26,6 +28,12 @@ public class DaprBeanPostProcessor implements BeanPostProcessor { private static final ObjectMapper MAPPER = new ObjectMapper(); + private final EmbeddedValueResolver embeddedValueResolver; + + DaprBeanPostProcessor(ConfigurableBeanFactory beanFactory) { + embeddedValueResolver = new EmbeddedValueResolver(beanFactory); + } + /** * {@inheritDoc} */ @@ -35,7 +43,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro return null; } - subscribeToTopics(bean.getClass()); + subscribeToTopics(bean.getClass(), embeddedValueResolver); return bean; } @@ -52,12 +60,12 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw * Subscribe to topics based on {@link Topic} annotations on the given class and any of ancestor classes. * @param clazz Controller class where {@link Topic} is expected. */ - private static void subscribeToTopics(Class clazz) { + private static void subscribeToTopics(Class clazz, EmbeddedValueResolver embeddedValueResolver) { if (clazz == null) { return; } - subscribeToTopics(clazz.getSuperclass()); + subscribeToTopics(clazz.getSuperclass(), embeddedValueResolver); for (Method method : clazz.getDeclaredMethods()) { Topic topic = method.getAnnotation(Topic.class); if (topic == null) { @@ -71,8 +79,8 @@ private static void subscribeToTopics(Class clazz) { route = mapping.path()[0]; } - String topicName = topic.name(); - String pubSubName = topic.pubsubName(); + 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> typeRef From c23985e47cb3972e13bbdb48cc41a7ff666ee7fd Mon Sep 17 00:00:00 2001 From: Justin Rovang Date: Wed, 26 May 2021 17:49:20 -0500 Subject: [PATCH 2/6] [WIP] Updated SubscriberController to use SPEL in @Topic --- .../test/java/io/dapr/it/pubsub/http/SubscriberController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberController.java b/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberController.java index 478c1dde37..eb387a8bf7 100644 --- a/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberController.java +++ b/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberController.java @@ -77,7 +77,7 @@ public Mono handleBinaryMessage(@RequestBody(required = false) CloudEvent }); } - @Topic(name = "anothertopic", pubsubName = "messagebus") + @Topic(name = "#{'another'.concat('topic')}", pubsubName = "${pubsubName:messagebus}") @PostMapping(path = "/route3") public Mono handleMessageAnotherTopic(@RequestBody(required = false) CloudEvent envelope) { return Mono.fromRunnable(() -> { From 757007e0410128e30d5583a9f5525a9139633bd4 Mon Sep 17 00:00:00 2001 From: Justin Rovang Date: Fri, 4 Jun 2021 20:27:12 -0500 Subject: [PATCH 3/6] 554 - SPEL for @Topic attributes: Updated documentation and examples --- .../src/main/java/io/dapr/examples/pubsub/http/README.md | 7 +++++-- .../io/dapr/examples/pubsub/http/SubscriberController.java | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md index 1e7fe7062c..44efcd9478 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md @@ -51,13 +51,16 @@ public class Subscriber { ``` `DaprApplication.start()` Method will run an Spring Boot application that registers the `SubscriberController`, which exposes the message retrieval as a POST request. The Dapr's sidecar is the one that performs the actual call to the controller, based on the pubsub features. -This Spring Controller handles the message endpoint, Printing the message which is received as the POST body. The topic subscription in Dapr is handled automatically via the `@Topic` annotation. See the code snippet below: +This Spring Controller handles the message endpoint, Printing the message which is received as the POST body. + +The topic subscription in Dapr is handled automatically via the `@Topic` annotation - which also supports Spring expressions if you wish to dynamically configure it. +See the code snippet below: ```java @RestController public class SubscriberController { ///... - @Topic(name = "testingtopic", pubsubName = "messagebus") + @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) byte[] body, @RequestHeader Map headers) { diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java index 5dba0a074b..83de3cba07 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java @@ -26,7 +26,7 @@ public class SubscriberController { * @param cloudEvent The cloud event received. * @return A message containing the time. */ - @Topic(name = "testingtopic", pubsubName = "messagebus") + @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) { return Mono.fromRunnable(() -> { From c8f4607307c4fac6bd7d3b9b1e13b91092d15f59 Mon Sep 17 00:00:00 2001 From: Justin Rovang Date: Fri, 11 Jun 2021 11:19:20 -0500 Subject: [PATCH 4/6] Updated documentation as discussed --- .../src/main/java/io/dapr/examples/pubsub/http/README.md | 6 ++++-- .../io/dapr/examples/pubsub/http/SubscriberController.java | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md index 44efcd9478..132dd4a1a9 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md @@ -53,8 +53,10 @@ public class Subscriber { This Spring Controller handles the message endpoint, Printing the message which is received as the POST body. -The topic subscription in Dapr is handled automatically via the `@Topic` annotation - which also supports Spring expressions if you wish to dynamically configure it. -See the code snippet below: +The topic subscription in Dapr is handled automatically via the `@Topic` annotation - which also supports the same expressions that can be used in +[Spring's @Value annotations](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations). + +The code snippet below shows how to create a subscription using the `@Topic` annotation showcasing expression support (if `myAppProperty` doesn't exist as a property, the value defaults to the string: `messagebus`). ```java @RestController diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java index 83de3cba07..ca697e22ec 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java @@ -26,6 +26,11 @@ public class SubscriberController { * @param cloudEvent The cloud event received. * @return A message containing the time. */ + /* + If 'myAppProperty' doesn't exist, default to 'messagebus' - behavior is the same as what can + be used in Spring's @Value annotation + https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations + */ @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) { From 2600cbc099f9bf9eed9c223d9ed32411465f1a62 Mon Sep 17 00:00:00 2001 From: Artur Souza Date: Sun, 13 Jun 2021 15:05:55 -0700 Subject: [PATCH 5/6] Update README.md --- .../src/main/java/io/dapr/examples/pubsub/http/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md index 132dd4a1a9..90c6e48857 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/README.md +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/README.md @@ -51,12 +51,12 @@ public class Subscriber { ``` `DaprApplication.start()` Method will run an Spring Boot application that registers the `SubscriberController`, which exposes the message retrieval as a POST request. The Dapr's sidecar is the one that performs the actual call to the controller, based on the pubsub features. -This Spring Controller handles the message endpoint, Printing the message which is received as the POST body. +This Spring Controller handles the message endpoint, printing the message which is received as the POST body. -The topic subscription in Dapr is handled automatically via the `@Topic` annotation - which also supports the same expressions that can be used in +The subscription's topic in Dapr is handled automatically via the `@Topic` annotation - which also supports the same expressions in [Spring's @Value annotations](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations). -The code snippet below shows how to create a subscription using the `@Topic` annotation showcasing expression support (if `myAppProperty` doesn't exist as a property, the value defaults to the string: `messagebus`). +The code snippet below shows how to create a subscription using the `@Topic` annotation showcasing expression support. In this case, `myAppProperty` is a Java property that does not exist, so the expression resolves to the default value (`messagebus`). ```java @RestController From e6150ae42e5646e9e9394a5f910935ac4011cbdb Mon Sep 17 00:00:00 2001 From: Artur Souza Date: Sun, 13 Jun 2021 17:53:50 -0700 Subject: [PATCH 6/6] Update SubscriberController.java --- .../io/dapr/examples/pubsub/http/SubscriberController.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java index ca697e22ec..83de3cba07 100644 --- a/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java +++ b/examples/src/main/java/io/dapr/examples/pubsub/http/SubscriberController.java @@ -26,11 +26,6 @@ public class SubscriberController { * @param cloudEvent The cloud event received. * @return A message containing the time. */ - /* - If 'myAppProperty' doesn't exist, default to 'messagebus' - behavior is the same as what can - be used in Spring's @Value annotation - https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations - */ @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) {