Skip to content

Commit

Permalink
Added SPEL evaluation against spring boot @Topic attributes (#556)
Browse files Browse the repository at this point in the history
* [WIP] Added SPEL evaluation against spring boot @Topic name and pubsubname attributes

* [WIP] Updated SubscriberController to use SPEL in @Topic

* 554 - SPEL for @Topic attributes: Updated documentation and examples

* Updated documentation as discussed

* Update README.md

* Update SubscriberController.java

Co-authored-by: Artur Souza <artursouza.ms@outlook.com>
  • Loading branch information
rovangju and artursouza committed Jun 18, 2021
1 parent 5c05f3d commit 0e5e311
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 9 deletions.
9 changes: 7 additions & 2 deletions examples/src/main/java/io/dapr/examples/pubsub/http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,18 @@ 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 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. In this case, `myAppProperty` is a Java property that does not exist, so the expression resolves to the default value (`messagebus`).

```java
@RestController
public class SubscriberController {
///...
@Topic(name = "testingtopic", pubsubName = "messagebus")
@Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}")
@PostMapping(path = "/testingtopic")
public Mono<Void> handleMessage(@RequestBody(required = false) byte[] body,
@RequestHeader Map<String, String> headers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Void> handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) {
return Mono.fromRunnable(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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}
*/
Expand All @@ -35,7 +43,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
return null;
}

subscribeToTopics(bean.getClass());
subscribeToTopics(bean.getClass(), embeddedValueResolver);

return bean;
}
Expand All @@ -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) {
Expand All @@ -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<HashMap<String, String>> typeRef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public Mono<Void> handleBinaryMessage(@RequestBody(required = false) CloudEvent
});
}

@Topic(name = "anothertopic", pubsubName = "messagebus")
@Topic(name = "#{'another'.concat('topic')}", pubsubName = "${pubsubName:messagebus}")
@PostMapping(path = "/route3")
public Mono<Void> handleMessageAnotherTopic(@RequestBody(required = false) CloudEvent envelope) {
return Mono.fromRunnable(() -> {
Expand Down

0 comments on commit 0e5e311

Please sign in to comment.