diff --git a/.gitignore b/.gitignore index 0314f663d..d39d713b8 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,6 @@ hs_err_pid* /docs/dapr-sdk /proto/dapr /proto/daprclient + +# macOS +.DS_Store diff --git a/README.md b/README.md index b36dfb006..89d2e0c05 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,12 @@ For a Maven project, add the following to your `pom.xml` file: dapr-sdk-actors 0.3.0 + + + io.dapr + dapr-sdk-springboot + 0.4.0-SNAPSHOT + com.squareup.okhttp3 @@ -103,6 +109,8 @@ dependencies { compile('io.dapr:dapr-sdk:0.3.0') // Dapr's SDK for Actors (optional). compile('io.dapr:dapr-sdk-actors:0.3.0') + // Dapr's SDK integration with SpringBoot (optional). + compile('io.dapr:dapr-sdk-springboot:0.4.0-SNAPSHOT') // If needed, force conflict resolution for okhttp3. configurations.all { diff --git a/examples/pom.xml b/examples/pom.xml index 46b01054e..856f66d57 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -73,6 +73,11 @@ spring-boot-autoconfigure 2.2.2.RELEASE + + io.dapr + dapr-sdk-springboot + ${project.version} + io.dapr dapr-sdk-actors diff --git a/examples/src/main/java/io/dapr/examples/actors/http/DemoActorService.java b/examples/src/main/java/io/dapr/examples/actors/http/DemoActorService.java index 077d47937..b7ecbebbb 100644 --- a/examples/src/main/java/io/dapr/examples/actors/http/DemoActorService.java +++ b/examples/src/main/java/io/dapr/examples/actors/http/DemoActorService.java @@ -12,6 +12,8 @@ import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; +import java.time.Duration; + /** * Service for Actor runtime. * 1. Build and install jars: @@ -36,7 +38,16 @@ public class DemoActorService { CommandLine cmd = parser.parse(options, args); // If port string is not valid, it will throw an exception. - int port = Integer.parseInt(cmd.getOptionValue("port")); + final int port = Integer.parseInt(cmd.getOptionValue("port")); + + // Idle timeout until actor instance is deactivated. + ActorRuntime.getInstance().getConfig().setActorIdleTimeout(Duration.ofSeconds(30)); + // How often actor instances are scanned for deactivation and balance. + ActorRuntime.getInstance().getConfig().setActorScanInterval(Duration.ofSeconds(10)); + // How long to wait until for draining an ongoing API call for an actor instance. + ActorRuntime.getInstance().getConfig().setDrainOngoingCallTimeout(Duration.ofSeconds(10)); + // Determines whether to drain API calls for actors instances being balanced. + ActorRuntime.getInstance().getConfig().setDrainBalancedActors(true); // Register the Actor class. ActorRuntime.getInstance().registerActor(DemoActorImpl.class); diff --git a/examples/src/main/java/io/dapr/examples/actors/http/README.md b/examples/src/main/java/io/dapr/examples/actors/http/README.md index f48706ebe..3e151872e 100644 --- a/examples/src/main/java/io/dapr/examples/actors/http/README.md +++ b/examples/src/main/java/io/dapr/examples/actors/http/README.md @@ -38,7 +38,6 @@ mvn install The first Java class is `DemoActorService`. Its job is to register an implementation of `DemoActor` in the Dapr's Actor runtime. In `DemoActorService.java` file, you will find the `DemoActorService` class and the `main` method. See the code snippet below: ```java -@SpringBootApplication public class DemoActorService { public static void main(String[] args) throws Exception { 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 611c7dd11..840b18dbb 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 @@ -44,18 +44,14 @@ 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 recieved message which is recieved as the POST body. 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. See the code snippet below: ```java @RestController public class SubscriberController { ///... - @GetMapping("/dapr/subscribe") - public byte[] daprConfig() throws Exception { - return SERIALIZER.serialize(new String[] { "message" }); - } - - @PostMapping(path = "/message") + @Topic(name = "testingtopic") + @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) byte[] body, @RequestHeader Map headers) { return Mono.fromRunnable(() -> { 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 2700ba63e..8106ab18f 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 @@ -5,6 +5,7 @@ package io.dapr.examples.pubsub.http; +import io.dapr.Topic; import io.dapr.client.domain.CloudEvent; import io.dapr.serializer.DefaultObjectSerializer; import org.springframework.web.bind.annotation.GetMapping; @@ -22,22 +23,13 @@ import java.util.Map; @RestController public class SubscriberController { - /** - * Dapr's default serializer/deserializer. - */ - private static final DefaultObjectSerializer SERIALIZER = new DefaultObjectSerializer(); - - @GetMapping("/dapr/subscribe") - public byte[] daprConfig() throws Exception { - return SERIALIZER.serialize(new String[]{"testingtopic"}); - } - /** * Handles a registered publish endpoint on this app. * @param body The body of the http message. * @param headers The headers of the http message. * @return A message containing the time. */ + @Topic(name = "testingtopic") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) byte[] body, @RequestHeader Map headers) { diff --git a/examples/src/main/java/io/dapr/springboot/DaprApplication.java b/examples/src/main/java/io/dapr/springboot/DaprApplication.java index 22d22ea6b..f97c7bc36 100644 --- a/examples/src/main/java/io/dapr/springboot/DaprApplication.java +++ b/examples/src/main/java/io/dapr/springboot/DaprApplication.java @@ -10,6 +10,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Dapr's HTTP callback implementation via SpringBoot. + * Scanning package io.dapr.springboot is required. */ @SpringBootApplication(scanBasePackages = {"io.dapr.springboot", "io.dapr.examples"}) public class DaprApplication { diff --git a/pom.xml b/pom.xml index dffc777f9..25cb78b89 100644 --- a/pom.xml +++ b/pom.xml @@ -252,6 +252,7 @@ sdk-autogen sdk sdk-actors + sdk-springboot examples diff --git a/sdk-springboot/pom.xml b/sdk-springboot/pom.xml new file mode 100644 index 000000000..9aa580dda --- /dev/null +++ b/sdk-springboot/pom.xml @@ -0,0 +1,168 @@ + + 4.0.0 + + + io.dapr + dapr-sdk-parent + 0.4.0-SNAPSHOT + + + dapr-sdk-springboot + jar + 0.4.0-SNAPSHOT + dapr-sdk-springboot + SDK extension for Springboot + + + + + false + + central + libs-release + https://repo.spring.io/libs-release + + + + + false + + + + + io.dapr + dapr-sdk + ${project.version} + + + io.dapr + dapr-sdk-actors + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.github.gmazzo + okhttp-mock + 1.3.2 + test + + + org.junit.jupiter + junit-jupiter-api + 5.5.2 + test + + + org.springframework + spring-beans + 5.2.3.RELEASE + compile + + + org.springframework + spring-web + 5.2.2.RELEASE + compile + + + org.springframework + spring-web + 5.2.2.RELEASE + compile + + + org.springframework + spring-context + 5.2.2.RELEASE + compile + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.4 + + + default-prepare-agent + + prepare-agent + + + + report + test + + report + + + target/jacoco-report/ + + + + check + + check + + + + + BUNDLE + + + LINE + COVEREDRATIO + 80% + + + + + + + + + + + + diff --git a/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java b/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java new file mode 100644 index 000000000..c247c1dbd --- /dev/null +++ b/sdk-springboot/src/main/java/io/dapr/springboot/DaprBeanPostProcessor.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ + +package io.dapr.springboot; + +import io.dapr.Topic; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +@Component +public class DaprBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (bean == null) { + return null; + } + + subscribeToTopics(bean.getClass()); + + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + private static void subscribeToTopics(Class clazz) { + if (clazz == null) { + return; + } + + subscribeToTopics(clazz.getSuperclass()); + for (Method method : clazz.getDeclaredMethods()) { + Topic topic = method.getAnnotation(Topic.class); + if (topic == null) { + continue; + } + + String topicName = topic.name(); + if ((topicName != null) && (topicName.length() > 0)) { + DaprRuntime.getInstance().addSubscribedTopic(topicName); + } + } + } +} diff --git a/examples/src/main/java/io/dapr/springboot/DaprController.java b/sdk-springboot/src/main/java/io/dapr/springboot/DaprController.java similarity index 85% rename from examples/src/main/java/io/dapr/springboot/DaprController.java rename to sdk-springboot/src/main/java/io/dapr/springboot/DaprController.java index c1b46885d..35000fe2e 100644 --- a/examples/src/main/java/io/dapr/springboot/DaprController.java +++ b/sdk-springboot/src/main/java/io/dapr/springboot/DaprController.java @@ -6,6 +6,7 @@ package io.dapr.springboot; import io.dapr.actors.runtime.ActorRuntime; +import io.dapr.serializer.DefaultObjectSerializer; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -21,16 +22,21 @@ import reactor.core.publisher.Mono; @RestController public class DaprController { - @GetMapping("/") - public String index() { - return "Greetings from Dapr!"; - } + /** + * Dapr's default serializer/deserializer. + */ + private static final DefaultObjectSerializer SERIALIZER = new DefaultObjectSerializer(); @GetMapping("/dapr/config") public byte[] daprConfig() throws Exception { return ActorRuntime.getInstance().serializeConfig(); } + @GetMapping("/dapr/subscribe") + public byte[] daprSubscribe() throws Exception { + return SERIALIZER.serialize(DaprRuntime.getInstance().listSubscribedTopics()); + } + @PostMapping(path = "/actors/{type}/{id}") public Mono activateActor(@PathVariable("type") String type, @PathVariable("id") String id) throws Exception { diff --git a/sdk-springboot/src/main/java/io/dapr/springboot/DaprRuntime.java b/sdk-springboot/src/main/java/io/dapr/springboot/DaprRuntime.java new file mode 100644 index 000000000..7739cc485 --- /dev/null +++ b/sdk-springboot/src/main/java/io/dapr/springboot/DaprRuntime.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ + +package io.dapr.springboot; + +import java.util.HashSet; +import java.util.Set; + +class DaprRuntime { + + /** + * The singleton instance. + */ + private static volatile DaprRuntime instance; + + private final Set subscribedTopics = new HashSet<>(); + + /** + * Private constructor to make this singleton. + */ + private DaprRuntime() { + } + + /** + * Returns an DaprRuntime object. + * + * @return An DaprRuntime object. + */ + public static DaprRuntime getInstance() { + if (instance == null) { + synchronized (DaprRuntime.class) { + if (instance == null) { + instance = new DaprRuntime(); + } + } + } + + return instance; + } + + public synchronized void addSubscribedTopic(String topicName) { + if (!this.subscribedTopics.contains(topicName)) { + this.subscribedTopics.add(topicName); + } + } + + public synchronized String[] listSubscribedTopics() { + return this.subscribedTopics.toArray(new String[0]); + } +} diff --git a/sdk-tests/pom.xml b/sdk-tests/pom.xml index 66012bcff..235a2f51d 100644 --- a/sdk-tests/pom.xml +++ b/sdk-tests/pom.xml @@ -41,6 +41,12 @@ ${dapr.sdk.version} test + + io.dapr + dapr-sdk-springboot + ${dapr.sdk.version} + test + junit junit diff --git a/sdk-tests/src/test/java/io/dapr/it/actors/app/TestApplication.java b/sdk-tests/src/test/java/io/dapr/it/actors/app/TestApplication.java index 7847c0218..4a1089e95 100644 --- a/sdk-tests/src/test/java/io/dapr/it/actors/app/TestApplication.java +++ b/sdk-tests/src/test/java/io/dapr/it/actors/app/TestApplication.java @@ -11,7 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Dapr's HTTP callback implementation via SpringBoot. */ -@SpringBootApplication(scanBasePackages = {"io.dapr.it.actors.app"}) +@SpringBootApplication(scanBasePackages = {"io.dapr.springboot", "io.dapr.it.actors.app"}) public class TestApplication { /** diff --git a/sdk-tests/src/test/java/io/dapr/it/actors/app/TestController.java b/sdk-tests/src/test/java/io/dapr/it/actors/app/TestController.java deleted file mode 100644 index de289b526..000000000 --- a/sdk-tests/src/test/java/io/dapr/it/actors/app/TestController.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - */ - -package io.dapr.it.actors.app; - -import io.dapr.actors.runtime.ActorRuntime; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; - -/** - * SpringBoot Controller to handle callback APIs for Dapr. - */ -@RestController -class TestController { - - @GetMapping("/") - public String index() { - return "Greetings from Dapr!"; - } - - @GetMapping("/dapr/config") - public byte[] daprConfig() throws Exception { - return ActorRuntime.getInstance().serializeConfig(); - } - - @PostMapping(path = "/actors/{type}/{id}") - public Mono activateActor(@PathVariable("type") String type, - @PathVariable("id") String id) throws Exception { - return ActorRuntime.getInstance().activate(type, id); - } - - @DeleteMapping(path = "/actors/{type}/{id}") - public Mono deactivateActor(@PathVariable("type") String type, - @PathVariable("id") String id) throws Exception { - return ActorRuntime.getInstance().deactivate(type, id); - } - - @PutMapping(path = "/actors/{type}/{id}/method/{method}") - public Mono invokeActorMethod(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("method") String method, - @RequestBody(required = false) byte[] body) { - return ActorRuntime.getInstance().invoke(type, id, method, body); - } - - @PutMapping(path = "/actors/{type}/{id}/method/timer/{timer}") - public Mono invokeActorTimer(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("timer") String timer) { - return ActorRuntime.getInstance().invokeTimer(type, id, timer); - } - - @PutMapping(path = "/actors/{type}/{id}/method/remind/{reminder}") - public Mono invokeActorReminder(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("reminder") String reminder, - @RequestBody(required = false) byte[] body) { - return ActorRuntime.getInstance().invokeReminder(type, id, reminder, body); - } -} diff --git a/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprApplication.java b/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprApplication.java index 6045fc405..520b2db57 100644 --- a/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprApplication.java +++ b/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprApplication.java @@ -11,7 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Dapr's HTTP callback implementation via SpringBoot. */ -@SpringBootApplication(scanBasePackages = {"io.dapr.it.actors.services.springboot"}) +@SpringBootApplication(scanBasePackages = {"io.dapr.springboot", "io.dapr.it.actors.services.springboot"}) public class DaprApplication { /** diff --git a/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprController.java b/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprController.java deleted file mode 100644 index 3d6df071d..000000000 --- a/sdk-tests/src/test/java/io/dapr/it/actors/services/springboot/DaprController.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - */ - -package io.dapr.it.actors.services.springboot; - -import io.dapr.actors.runtime.ActorRuntime; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; - -/** - * SpringBoot Controller to handle callback APIs for Dapr. - */ -@RestController -public class DaprController { - - @GetMapping("/") - public String index() { - return "Greetings from Dapr!"; - } - - @GetMapping("/dapr/config") - public byte[] daprConfig() throws Exception { - return ActorRuntime.getInstance().serializeConfig(); - } - - @PostMapping(path = "/actors/{type}/{id}") - public Mono activateActor(@PathVariable("type") String type, - @PathVariable("id") String id) throws Exception { - return ActorRuntime.getInstance().activate(type, id); - } - - @DeleteMapping(path = "/actors/{type}/{id}") - public Mono deactivateActor(@PathVariable("type") String type, - @PathVariable("id") String id) throws Exception { - return ActorRuntime.getInstance().deactivate(type, id); - } - - @PutMapping(path = "/actors/{type}/{id}/method/{method}") - public Mono invokeActorMethod(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("method") String method, - @RequestBody(required = false) byte[] body) { - return ActorRuntime.getInstance().invoke(type, id, method, body); - } - - @PutMapping(path = "/actors/{type}/{id}/method/timer/{timer}") - public Mono invokeActorTimer(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("timer") String timer) { - return ActorRuntime.getInstance().invokeTimer(type, id, timer); - } - - @PutMapping(path = "/actors/{type}/{id}/method/remind/{reminder}") - public Mono invokeActorReminder(@PathVariable("type") String type, - @PathVariable("id") String id, - @PathVariable("reminder") String reminder, - @RequestBody(required = false) byte[] body) { - return ActorRuntime.getInstance().invokeReminder(type, id, reminder, body); - } -} diff --git a/sdk-tests/src/test/java/io/dapr/it/binding/http/InputBindingController.java b/sdk-tests/src/test/java/io/dapr/it/binding/http/InputBindingController.java index 1fd35f23a..2bd4bdfac 100644 --- a/sdk-tests/src/test/java/io/dapr/it/binding/http/InputBindingController.java +++ b/sdk-tests/src/test/java/io/dapr/it/binding/http/InputBindingController.java @@ -22,11 +22,6 @@ public class InputBindingController { private static final List messagesReceived = new ArrayList(); - @GetMapping("/dapr/config") - public String daprConfig() throws Exception { - return "{}"; - } - @PostMapping(path = "/sample123") @PutMapping(path = "/sample123") public void handleInputBinding(@RequestBody(required = false) String body) { diff --git a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java index f2dd6f6df..70817bc56 100644 --- a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java +++ b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java @@ -12,7 +12,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Service for subscriber. */ -@SpringBootApplication(scanBasePackages = {"io.dapr.it.methodinvoke.http"}) +@SpringBootApplication public class MethodInvokeService { public static final String SUCCESS_MESSAGE = "dapr initialized. Status: Running. Init Elapsed"; 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 507676879..16e772a5f 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 @@ -5,6 +5,7 @@ package io.dapr.it.pubsub.http; +import io.dapr.Topic; import io.dapr.client.domain.CloudEvent; import io.dapr.serializer.DefaultObjectSerializer; import org.springframework.web.bind.annotation.*; @@ -22,21 +23,12 @@ public class SubscriberController { private static final List messagesReceived = new ArrayList(); - /** - * Dapr's default serializer/deserializer. - */ - private static final DefaultObjectSerializer SERIALIZER = new DefaultObjectSerializer (); - - @GetMapping("/dapr/subscribe") - public byte[] daprConfig() throws Exception { - return SERIALIZER.serialize(new String[] { "testingtopic" }); - } - @GetMapping(path = "/messages") public List getMessages() { return messagesReceived; } + @Topic(name = "testingtopic") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) byte[] body, @RequestHeader Map headers) { diff --git a/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberService.java b/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberService.java index 4426ec22e..169a2028d 100644 --- a/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberService.java +++ b/sdk-tests/src/test/java/io/dapr/it/pubsub/http/SubscriberService.java @@ -13,7 +13,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Service for subscriber. */ -@SpringBootApplication(scanBasePackages = {"io.dapr.it.pubsub.http"}) +@SpringBootApplication(scanBasePackages = {"io.dapr.springboot", "io.dapr.it.pubsub.http"}) public class SubscriberService { public static final String SUCCESS_MESSAGE = "dapr initialized. Status: Running. Init Elapsed"; diff --git a/sdk-tests/src/test/java/io/dapr/it/secrets/SecretsClientIT.java b/sdk-tests/src/test/java/io/dapr/it/secrets/SecretsClientIT.java index d3582ade9..f045a8057 100644 --- a/sdk-tests/src/test/java/io/dapr/it/secrets/SecretsClientIT.java +++ b/sdk-tests/src/test/java/io/dapr/it/secrets/SecretsClientIT.java @@ -7,7 +7,6 @@ package io.dapr.it.secrets; import com.bettercloud.vault.Vault; import com.bettercloud.vault.VaultConfig; -import com.bettercloud.vault.response.LogicalResponse; import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprClientGrpc; diff --git a/sdk/src/main/java/io/dapr/Topic.java b/sdk/src/main/java/io/dapr/Topic.java new file mode 100644 index 000000000..167005238 --- /dev/null +++ b/sdk/src/main/java/io/dapr/Topic.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ + +package io.dapr; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Topic { + + /** + * Name of topic to be subscribed to. + * + * @return Topic's name. + */ + String name(); +}