How-To: Use output bindings to interface with external resources

Invoke external systems with output bindings

With output bindings, you can invoke external resources without depending on special SDK or libraries. An output binding represents a resource that Dapr uses to invoke and send messages to. For a complete sample showing output bindings, walk through the tutorial.

Diagram showing bindings of example service

This guide uses a Kafka binding as an example. You can find your preferred binding spec from the list of bindings components.

Create a binding

Create a new binding component with the name of checkout.

Within the metadata section, configure Kafka-related properties, such as:

  • The topic to which you’ll publish the message
  • The broker

Create the following binding.yaml file and save to a components sub-folder in your application directory.

Use the --components-path flag with dapr run to point to your custom components directory.

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: checkout
  5. spec:
  6. type: bindings.kafka
  7. version: v1
  8. metadata:
  9. # Kafka broker connection setting
  10. - name: brokers
  11. value: localhost:9092
  12. # consumer configuration: topic and consumer group
  13. - name: topics
  14. value: sample
  15. - name: consumerGroup
  16. value: group1
  17. # publisher configuration: topic
  18. - name: publishTopic
  19. value: sample
  20. - name: authRequired
  21. value: "false"

To deploy the following binding.yaml file into a Kubernetes cluster, run kubectl apply -f binding.yaml.

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: checkout
  5. spec:
  6. type: bindings.kafka
  7. version: v1
  8. metadata:
  9. # Kafka broker connection setting
  10. - name: brokers
  11. value: localhost:9092
  12. # consumer configuration: topic and consumer group
  13. - name: topics
  14. value: sample
  15. - name: consumerGroup
  16. value: group1
  17. # publisher configuration: topic
  18. - name: publishTopic
  19. value: sample
  20. - name: authRequired
  21. value: "false"

Send an event (output binding)

Below are code examples that leverage Dapr SDKs to interact with an output binding.

  1. //dependencies
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Threading.Tasks;
  7. using Dapr.Client;
  8. using Microsoft.AspNetCore.Mvc;
  9. using System.Threading;
  10. //code
  11. namespace EventService
  12. {
  13. class Program
  14. {
  15. static async Task Main(string[] args)
  16. {
  17. string BINDING_NAME = "checkout";
  18. string BINDING_OPERATION = "create";
  19. while(true)
  20. {
  21. System.Threading.Thread.Sleep(5000);
  22. Random random = new Random();
  23. int orderId = random.Next(1,1000);
  24. using var client = new DaprClientBuilder().Build();
  25. //Using Dapr SDK to invoke output binding
  26. await client.InvokeBindingAsync(BINDING_NAME, BINDING_OPERATION, orderId);
  27. Console.WriteLine("Sending message: " + orderId);
  28. }
  29. }
  30. }
  31. }
  1. //dependencies
  2. import io.dapr.client.DaprClient;
  3. import io.dapr.client.DaprClientBuilder;
  4. import io.dapr.client.domain.HttpExtension;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import java.util.Random;
  9. import java.util.concurrent.TimeUnit;
  10. //code
  11. @SpringBootApplication
  12. public class OrderProcessingServiceApplication {
  13. private static final Logger log = LoggerFactory.getLogger(OrderProcessingServiceApplication.class);
  14. public static void main(String[] args) throws InterruptedException{
  15. String BINDING_NAME = "checkout";
  16. String BINDING_OPERATION = "create";
  17. while(true) {
  18. TimeUnit.MILLISECONDS.sleep(5000);
  19. Random random = new Random();
  20. int orderId = random.nextInt(1000-1) + 1;
  21. DaprClient client = new DaprClientBuilder().build();
  22. //Using Dapr SDK to invoke output binding
  23. client.invokeBinding(BINDING_NAME, BINDING_OPERATION, orderId).block();
  24. log.info("Sending message: " + orderId);
  25. }
  26. }
  27. }
  1. #dependencies
  2. import random
  3. from time import sleep
  4. import requests
  5. import logging
  6. import json
  7. from dapr.clients import DaprClient
  8. #code
  9. logging.basicConfig(level = logging.INFO)
  10. BINDING_NAME = 'checkout'
  11. BINDING_OPERATION = 'create'
  12. while True:
  13. sleep(random.randrange(50, 5000) / 1000)
  14. orderId = random.randint(1, 1000)
  15. with DaprClient() as client:
  16. #Using Dapr SDK to invoke output binding
  17. resp = client.invoke_binding(BINDING_NAME, BINDING_OPERATION, json.dumps(orderId))
  18. logging.basicConfig(level = logging.INFO)
  19. logging.info('Sending message: ' + str(orderId))
  1. //dependencies
  2. import (
  3. "context"
  4. "log"
  5. "math/rand"
  6. "time"
  7. "strconv"
  8. dapr "github.com/dapr/go-sdk/client"
  9. )
  10. //code
  11. func main() {
  12. BINDING_NAME := "checkout";
  13. BINDING_OPERATION := "create";
  14. for i := 0; i < 10; i++ {
  15. time.Sleep(5000)
  16. orderId := rand.Intn(1000-1) + 1
  17. client, err := dapr.NewClient()
  18. if err != nil {
  19. panic(err)
  20. }
  21. defer client.Close()
  22. ctx := context.Background()
  23. //Using Dapr SDK to invoke output binding
  24. in := &dapr.InvokeBindingRequest{ Name: BINDING_NAME, Operation: BINDING_OPERATION , Data: []byte(strconv.Itoa(orderId))}
  25. err = client.InvokeOutputBinding(ctx, in)
  26. log.Println("Sending message: " + strconv.Itoa(orderId))
  27. }
  28. }
  1. //dependencies
  2. import { DaprClient, CommunicationProtocolEnum } from "dapr-client";
  3. //code
  4. const daprHost = "127.0.0.1";
  5. (async function () {
  6. for (var i = 0; i < 10; i++) {
  7. await sleep(2000);
  8. const orderId = Math.floor(Math.random() * (1000 - 1) + 1);
  9. try {
  10. await sendOrder(orderId)
  11. } catch (err) {
  12. console.error(e);
  13. process.exit(1);
  14. }
  15. }
  16. })();
  17. async function sendOrder(orderId) {
  18. const BINDING_NAME = "checkout";
  19. const BINDING_OPERATION = "create";
  20. const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
  21. //Using Dapr SDK to invoke output binding
  22. const result = await client.binding.send(BINDING_NAME, BINDING_OPERATION, orderId);
  23. console.log("Sending message: " + orderId);
  24. }
  25. function sleep(ms) {
  26. return new Promise(resolve => setTimeout(resolve, ms));
  27. }

Invoke the output bindings endpoint on a running Dapr instance.

You can also invoke the output bindings endpoint using HTTP:

  1. curl -X POST -H 'Content-Type: application/json' http://localhost:3601/v1.0/bindings/checkout -d '{ "data": 100, "operation": "create" }'

As seen above:

  1. The example invoked the /binding endpoint with checkout, the name of the binding to invoke.
  2. The payload goes inside the mandatory data field, and can be any JSON serializable value.
  3. The operation field tells the binding what action it needs to take. For example, the Kafka binding supports the create operation.

You can check which operations (specific to each component) are supported for every output binding.

Watch this video on how to use bi-directional output bindings.

References

Last modified June 23, 2022: Merge pull request #2550 from ItalyPaleAle/cosmosdb-harcoded-dapr-version (cf03237)