--- type: docs title: "Dapr Java SDK" linkTitle: "Java" weight: 2000 description: Java SDK packages for developing Dapr applications --- ## Prerequisites [Complete initial setup and import the Java SDK into your project]({{< ref java >}}) ## Building blocks The Java SDK allows you to interface with all of the [Dapr building blocks]({{< ref building-blocks >}}). ### Invoke a service ```java import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; try (DaprClient client = (new DaprClientBuilder()).build()) { // invoke a 'GET' method (HTTP) skipping serialization: \say with a Mono return type // for gRPC set HttpExtension.NONE parameters below response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"name\":\"World!\"}", HttpExtension.GET, byte[].class).block(); // invoke a 'POST' method (HTTP) skipping serialization: to \say with a Mono return type response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"id\":\"100\", \"FirstName\":\"Value\", \"LastName\":\"Value\"}", HttpExtension.POST, byte[].class).block(); System.out.println(new String(response)); // invoke a 'POST' method (HTTP) with serialization: \employees with a Mono return type Employee newEmployee = new Employee("Nigel", "Guitarist"); Employee employeeResponse = client.invokeMethod(SERVICE_TO_INVOKE, "employees", newEmployee, HttpExtension.POST, Employee.class).block(); } ``` - For a full guide on service invocation visit [How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/invoke) for code samples and instructions to try out service invocation ### Save & get application state ```java import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; import io.dapr.client.domain.State; import reactor.core.publisher.Mono; try (DaprClient client = (new DaprClientBuilder()).build()) { // Save state client.saveState(STATE_STORE_NAME, FIRST_KEY_NAME, myClass).block(); // Get state State retrievedMessage = client.getState(STATE_STORE_NAME, FIRST_KEY_NAME, MyClass.class).block(); // Delete state client.deleteState(STATE_STORE_NAME, FIRST_KEY_NAME).block(); } ``` - For a full list of state operations visit [How-To: Get & save state]({{< ref howto-get-save-state.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/state) for code samples and instructions to try out state management ### Publish & subscribe to messages ##### Publish messages ```java import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; import io.dapr.client.domain.Metadata; import static java.util.Collections.singletonMap; try (DaprClient client = (new DaprClientBuilder()).build()) { client.publishEvent(PUBSUB_NAME, TOPIC_NAME, message, singletonMap(Metadata.TTL_IN_SECONDS, MESSAGE_TTL_IN_SECONDS)).block(); } ``` ##### Subscribe to messages ```java import com.fasterxml.jackson.databind.ObjectMapper; import io.dapr.Topic; import io.dapr.client.domain.BulkSubscribeAppResponse; import io.dapr.client.domain.BulkSubscribeAppResponseEntry; import io.dapr.client.domain.BulkSubscribeAppResponseStatus; import io.dapr.client.domain.BulkSubscribeMessage; import io.dapr.client.domain.BulkSubscribeMessageEntry; import io.dapr.client.domain.CloudEvent; import io.dapr.springboot.annotations.BulkSubscribe; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController public class SubscriberController { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopic") public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) { return Mono.fromRunnable(() -> { try { System.out.println("Subscriber got: " + cloudEvent.getData()); System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); } catch (Exception e) { throw new RuntimeException(e); } }); } @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}", rule = @Rule(match = "event.type == 'myevent.v2'", priority = 1)) @PostMapping(path = "/testingtopicV2") public Mono handleMessageV2(@RequestBody(required = false) CloudEvent envelope) { return Mono.fromRunnable(() -> { try { System.out.println("Subscriber got: " + cloudEvent.getData()); System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); } catch (Exception e) { throw new RuntimeException(e); } }); } @BulkSubscribe() @Topic(name = "testingtopicbulk", pubsubName = "${myAppProperty:messagebus}") @PostMapping(path = "/testingtopicbulk") public Mono handleBulkMessage( @RequestBody(required = false) BulkSubscribeMessage> bulkMessage) { return Mono.fromCallable(() -> { if (bulkMessage.getEntries().size() == 0) { return new BulkSubscribeAppResponse(new ArrayList()); } System.out.println("Bulk Subscriber received " + bulkMessage.getEntries().size() + " messages."); List entries = new ArrayList(); for (BulkSubscribeMessageEntry entry : bulkMessage.getEntries()) { try { System.out.printf("Bulk Subscriber message has entry ID: %s\n", entry.getEntryId()); CloudEvent cloudEvent = (CloudEvent) entry.getEvent(); System.out.printf("Bulk Subscriber got: %s\n", cloudEvent.getData()); entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.SUCCESS)); } catch (Exception e) { e.printStackTrace(); entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.RETRY)); } } return new BulkSubscribeAppResponse(entries); }); } } ``` ##### Bulk Publish Messages > Note: API is in Alpha stage ```java import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprPreviewClient; import io.dapr.client.domain.BulkPublishResponse; import io.dapr.client.domain.BulkPublishResponseFailedEntry; import java.util.ArrayList; import java.util.List; class Solution { public void publishMessages() { try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { // Create a list of messages to publish List messages = new ArrayList<>(); for (int i = 0; i < NUM_MESSAGES; i++) { String message = String.format("This is message #%d", i); messages.add(message); System.out.println("Going to publish message : " + message); } // Publish list of messages using the bulk publish API BulkPublishResponse res = client.publishEvents(PUBSUB_NAME, TOPIC_NAME, "text/plain", messages).block() } } } ``` - For a full guide on publishing messages and subscribing to a topic [How-To: Publish & subscribe]({{< ref howto-publish-subscribe.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/pubsub/http) for code samples and instructions to try out pub/sub ### Interact with output bindings ```java import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; try (DaprClient client = (new DaprClientBuilder()).build()) { // sending a class with message; BINDING_OPERATION="create" client.invokeBinding(BINDING_NAME, BINDING_OPERATION, myClass).block(); // sending a plain string client.invokeBinding(BINDING_NAME, BINDING_OPERATION, message).block(); } ``` - For a full guide on output bindings visit [How-To: Output bindings]({{< ref howto-bindings.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out output bindings. ### Interact with input bindings ```java import org.springframework.web.bind.annotation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RestController @RequestMapping("/") public class myClass { private static final Logger log = LoggerFactory.getLogger(myClass); @PostMapping(path = "/checkout") public Mono getCheckout(@RequestBody(required = false) byte[] body) { return Mono.fromRunnable(() -> log.info("Received Message: " + new String(body))); } } ``` - For a full guide on input bindings, visit [How-To: Input bindings]({{< ref howto-triggers >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out input bindings. ### Retrieve secrets ```java import com.fasterxml.jackson.databind.ObjectMapper; import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; import java.util.Map; try (DaprClient client = (new DaprClientBuilder()).build()) { Map secret = client.getSecret(SECRET_STORE_NAME, secretKey).block(); System.out.println(JSON_SERIALIZER.writeValueAsString(secret)); } ``` - For a full guide on secrets visit [How-To: Retrieve secrets]({{< ref howto-secrets.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/secrets) for code samples and instructions to try out retrieving secrets ### Actors An actor is an isolated, independent unit of compute and state with single-threaded execution. Dapr provides an actor implementation based on the [Virtual Actor pattern](https://www.microsoft.com/en-us/research/project/orleans-virtual-actors/), which provides a single-threaded programming model and where actors are garbage collected when not in use. With Dapr's implementaiton, you write your Dapr actors according to the Actor model, and Dapr leverages the scalability and reliability that the underlying platform provides. ```java import io.dapr.actors.ActorMethod; import io.dapr.actors.ActorType; import reactor.core.publisher.Mono; @ActorType(name = "DemoActor") public interface DemoActor { void registerReminder(); @ActorMethod(name = "echo_message") String say(String something); void clock(String message); @ActorMethod(returns = Integer.class) Mono incrementAndGet(int delta); } ``` - For a full guide on actors visit [How-To: Use virtual actors in Dapr]({{< ref howto-actors.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/actors) for code samples and instructions to try actors ### Get & Subscribe to application configurations > Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface ```java import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprPreviewClient; import io.dapr.client.domain.ConfigurationItem; import io.dapr.client.domain.GetConfigurationRequest; import io.dapr.client.domain.SubscribeConfigurationRequest; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { // Get configuration for a single key Mono item = client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY).block(); // Get configurations for multiple keys Mono> items = client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); // Subscribe to configuration changes Flux outFlux = client.subscribeConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); outFlux.subscribe(configItems -> configItems.forEach(...)); // Unsubscribe from configuration changes Mono unsubscribe = client.unsubscribeConfiguration(SUBSCRIPTION_ID, CONFIG_STORE_NAME) } ``` - For a full list of configuration operations visit [How-To: Manage configuration from a store]({{< ref howto-manage-configuration.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/configuration) for code samples and instructions to try out different configuration operations. ### Query saved state > Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface ```java import io.dapr.client.DaprClient; import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprPreviewClient; import io.dapr.client.domain.QueryStateItem; import io.dapr.client.domain.QueryStateRequest; import io.dapr.client.domain.QueryStateResponse; import io.dapr.client.domain.query.Query; import io.dapr.client.domain.query.Sorting; import io.dapr.client.domain.query.filters.EqFilter; try (DaprClient client = builder.build(); DaprPreviewClient previewClient = builder.buildPreviewClient()) { String searchVal = args.length == 0 ? "searchValue" : args[0]; // Create JSON data Listing first = new Listing(); first.setPropertyType("apartment"); first.setId("1000"); ... Listing second = new Listing(); second.setPropertyType("row-house"); second.setId("1002"); ... Listing third = new Listing(); third.setPropertyType("apartment"); third.setId("1003"); ... Listing fourth = new Listing(); fourth.setPropertyType("apartment"); fourth.setId("1001"); ... Map meta = new HashMap<>(); meta.put("contentType", "application/json"); // Save state SaveStateRequest request = new SaveStateRequest(STATE_STORE_NAME).setStates( new State<>("1", first, null, meta, null), new State<>("2", second, null, meta, null), new State<>("3", third, null, meta, null), new State<>("4", fourth, null, meta, null) ); client.saveBulkState(request).block(); // Create query and query state request Query query = new Query() .setFilter(new EqFilter<>("propertyType", "apartment")) .setSort(Arrays.asList(new Sorting("id", Sorting.Order.DESC))); QueryStateRequest request = new QueryStateRequest(STATE_STORE_NAME) .setQuery(query); // Use preview client to call query state API QueryStateResponse result = previewClient.queryState(request, MyData.class).block(); // View Query state response System.out.println("Found " + result.getResults().size() + " items."); for (QueryStateItem item : result.getResults()) { System.out.println("Key: " + item.getKey()); System.out.println("Data: " + item.getValue()); } } ``` - For a full how-to on query state, visit [How-To: Query state]({{< ref howto-state-query-api.md >}}). - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/querystate) for complete code sample. ### Distributed lock ```java package io.dapr.examples.lock.grpc; import io.dapr.client.DaprClientBuilder; import io.dapr.client.DaprPreviewClient; import io.dapr.client.domain.LockRequest; import io.dapr.client.domain.UnlockRequest; import io.dapr.client.domain.UnlockResponseStatus; import reactor.core.publisher.Mono; public class DistributedLockGrpcClient { private static final String LOCK_STORE_NAME = "lockstore"; /** * Executes various methods to check the different apis. * * @param args arguments * @throws Exception throws Exception */ public static void main(String[] args) throws Exception { try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { System.out.println("Using preview client..."); tryLock(client); unlock(client); } } /** * Trying to get lock. * * @param client DaprPreviewClient object */ public static void tryLock(DaprPreviewClient client) { System.out.println("*******trying to get a free distributed lock********"); try { LockRequest lockRequest = new LockRequest(LOCK_STORE_NAME, "resouce1", "owner1", 5); Mono result = client.tryLock(lockRequest); System.out.println("Lock result -> " + (Boolean.TRUE.equals(result.block()) ? "SUCCESS" : "FAIL")); } catch (Exception ex) { System.out.println(ex.getMessage()); } } /** * Unlock a lock. * * @param client DaprPreviewClient object */ public static void unlock(DaprPreviewClient client) { System.out.println("*******unlock a distributed lock********"); try { UnlockRequest unlockRequest = new UnlockRequest(LOCK_STORE_NAME, "resouce1", "owner1"); Mono result = client.unlock(unlockRequest); System.out.println("Unlock result ->" + result.block().name()); } catch (Exception ex) { System.out.println(ex.getMessage()); } } } ``` - For a full how-to on distributed lock, visit [How-To: Use a Lock]({{< ref howto-use-distributed-lock.md >}}) - Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/lock) for complete code sample. ### Workflow > Dapr Workflow is currently in beta state. ```java package io.dapr.examples.workflows; import io.dapr.workflows.client.DaprWorkflowClient; import io.dapr.workflows.client.WorkflowInstanceStatus; import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * For setup instructions, see the README. */ public class DemoWorkflowClient { /** * The main method. * * @param args Input arguments (unused). * @throws InterruptedException If program has been interrupted. */ public static void main(String[] args) throws InterruptedException { DaprWorkflowClient client = new DaprWorkflowClient(); try (client) { String separatorStr = "*******"; System.out.println(separatorStr); String instanceId = client.scheduleNewWorkflow(DemoWorkflow.class, "input data"); System.out.printf("Started new workflow instance with random ID: %s%n", instanceId); System.out.println(separatorStr); System.out.println("**GetInstanceMetadata:Running Workflow**"); WorkflowInstanceStatus workflowMetadata = client.getInstanceState(instanceId, true); System.out.printf("Result: %s%n", workflowMetadata); System.out.println(separatorStr); System.out.println("**WaitForInstanceStart**"); try { WorkflowInstanceStatus waitForInstanceStartResult = client.waitForInstanceStart(instanceId, Duration.ofSeconds(60), true); System.out.printf("Result: %s%n", waitForInstanceStartResult); } catch (TimeoutException ex) { System.out.printf("waitForInstanceStart has an exception:%s%n", ex); } System.out.println(separatorStr); System.out.println("**SendExternalMessage**"); client.raiseEvent(instanceId, "TestEvent", "TestEventPayload"); System.out.println(separatorStr); System.out.println("** Registering parallel Events to be captured by allOf(t1,t2,t3) **"); client.raiseEvent(instanceId, "event1", "TestEvent 1 Payload"); client.raiseEvent(instanceId, "event2", "TestEvent 2 Payload"); client.raiseEvent(instanceId, "event3", "TestEvent 3 Payload"); System.out.printf("Events raised for workflow with instanceId: %s\n", instanceId); System.out.println(separatorStr); System.out.println("** Registering Event to be captured by anyOf(t1,t2,t3) **"); client.raiseEvent(instanceId, "e2", "event 2 Payload"); System.out.printf("Event raised for workflow with instanceId: %s\n", instanceId); System.out.println(separatorStr); System.out.println("**WaitForInstanceCompletion**"); try { WorkflowInstanceStatus waitForInstanceCompletionResult = client.waitForInstanceCompletion(instanceId, Duration.ofSeconds(60), true); System.out.printf("Result: %s%n", waitForInstanceCompletionResult); } catch (TimeoutException ex) { System.out.printf("waitForInstanceCompletion has an exception:%s%n", ex); } System.out.println(separatorStr); System.out.println("**purgeInstance**"); boolean purgeResult = client.purgeInstance(instanceId); System.out.printf("purgeResult: %s%n", purgeResult); System.out.println(separatorStr); System.out.println("**raiseEvent**"); String eventInstanceId = client.scheduleNewWorkflow(DemoWorkflow.class); System.out.printf("Started new workflow instance with random ID: %s%n", eventInstanceId); client.raiseEvent(eventInstanceId, "TestException", null); System.out.printf("Event raised for workflow with instanceId: %s\n", eventInstanceId); System.out.println(separatorStr); String instanceToTerminateId = "terminateMe"; client.scheduleNewWorkflow(DemoWorkflow.class, null, instanceToTerminateId); System.out.printf("Started new workflow instance with specified ID: %s%n", instanceToTerminateId); TimeUnit.SECONDS.sleep(5); System.out.println("Terminate this workflow instance manually before the timeout is reached"); client.terminateWorkflow(instanceToTerminateId, null); System.out.println(separatorStr); String restartingInstanceId = "restarting"; client.scheduleNewWorkflow(DemoWorkflow.class, null, restartingInstanceId); System.out.printf("Started new workflow instance with ID: %s%n", restartingInstanceId); System.out.println("Sleeping 30 seconds to restart the workflow"); TimeUnit.SECONDS.sleep(30); System.out.println("**SendExternalMessage: RestartEvent**"); client.raiseEvent(restartingInstanceId, "RestartEvent", "RestartEventPayload"); System.out.println("Sleeping 30 seconds to terminate the eternal workflow"); TimeUnit.SECONDS.sleep(30); client.terminateWorkflow(restartingInstanceId, null); } System.out.println("Exiting DemoWorkflowClient."); System.exit(0); } } ``` - For a full guide on workflows, visit: - [How-To: Author workflows]({{< ref howto-author-workflow.md >}}). - [How-To: Manage workflows]({{< ref howto-manage-workflow.md >}}). - [Learn more about how to use workflows with the Java SDK]({{< ref java-workflow.md >}}). ## Related links - [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples)