diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md
index ea45ababf..fa4308921 100644
--- a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md
+++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md
@@ -9,11 +9,11 @@ weight: 300
Output bindings enable you to invoke external resources without taking dependencies on special SDK or libraries.
For a complete sample showing output bindings, visit this [link](https://github.com/dapr/quickstarts/tree/master/bindings).
-Watch this [video](https://www.youtube.com/watch?v=ysklxm81MTs&feature=youtu.be&t=1960) on how to use bi-directional output bindings.
+## Example:
-
-
-
+The below code example loosely describes an application that processes orders. In the example, there is an order processing service which has a Dapr sidecar. The order processing service uses Dapr to invoke external resources(output binding).
+
+
## 1. Create a binding
@@ -21,7 +21,7 @@ An output binding represents a resource that Dapr uses to invoke and send messag
For the purpose of this guide, you'll use a Kafka binding. You can find a list of the different binding specs [here]({{< ref setup-bindings >}}).
-Create a new binding component with the name of `myevent`.
+Create a new binding component with the name of `checkout`.
Inside the `metadata` section, configure Kafka related properties such as the topic to publish the message to and the broker.
@@ -36,16 +36,24 @@ Create the following YAML file, named `binding.yaml`, and save this to a `compon
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
- name: myevent
- namespace: default
+ name: checkout
spec:
type: bindings.kafka
version: v1
metadata:
+ # Kafka broker connection setting
- name: brokers
value: localhost:9092
+ # consumer configuration: topic and consumer group
+ - name: topics
+ value: sample
+ - name: consumerGroup
+ value: group1
+ # publisher configuration: topic
- name: publishTopic
- value: topic1
+ value: sample
+ - name: authRequired
+ value: "false"
```
{{% /codetab %}}
@@ -59,38 +67,228 @@ To deploy this into a Kubernetes cluster, fill in the `metadata` connection deta
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
- name: myevent
- namespace: default
+ name: checkout
spec:
type: bindings.kafka
version: v1
metadata:
+ # Kafka broker connection setting
- name: brokers
value: localhost:9092
+ # consumer configuration: topic and consumer group
+ - name: topics
+ value: sample
+ - name: consumerGroup
+ value: group1
+ # publisher configuration: topic
- name: publishTopic
- value: topic1
+ value: sample
+ - name: authRequired
+ value: "false"
```
{{% /codetab %}}
{{< /tabs >}}
-## 2. Send an event
+## 2. Send an event(Output Binding)
+
+Below are code examples that leverage Dapr SDKs for saving and retrieving a single state.
+
+{{< tabs Dotnet Java Python Go Javascript>}}
+
+{{% codetab %}}
+
+```csharp
+//dependencies
+using Dapr.Client;
+
+//code
+namespace EventService
+{
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ string BINDING_NAME = "checkout";
+ string BINDING_OPERATION = "create";
+ int orderId = 100;
+ using var client = new DaprClientBuilder().Build();
+ //Using Dapr SDK to invoke output binding
+ await client.InvokeBindingAsync(BINDING_NAME, BINDING_OPERATION, orderId);
+ Console.WriteLine("Sending message: " + orderId);
+ }
+ }
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl dotnet run
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```java
+//dependencies
+import io.dapr.client.DaprClient;
+import io.dapr.client.DaprClientBuilder;
+import io.dapr.client.domain.HttpExtension;
+
+//code
+@SpringBootApplication
+public class OrderProcessingServiceApplication {
+
+ public static void main(String[] args) throws InterruptedException{
+ String BINDING_NAME = "checkout";
+ String BINDING_OPERATION = "create";
+ int orderId = 100;
+ DaprClient client = new DaprClientBuilder().build();
+ //Using Dapr SDK to invoke output binding
+ client.invokeBinding(BINDING_NAME, BINDING_OPERATION, orderId).block();
+ log.info("Sending message: " + orderId);
+ }
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```python
+#dependencies
+from dapr.clients import DaprClient
+
+#code
+BINDING_NAME = 'checkout'
+BINDING_OPERATION = 'create'
+
+orderId = 100
+with DaprClient() as client:
+ #Using Dapr SDK to invoke output binding
+ resp = client.invoke_binding(BINDING_NAME, BINDING_OPERATION, json.dumps(orderId))
+logging.basicConfig(level = logging.INFO)
+logging.info('Sending message: ' + str(orderId))
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```go
+//dependencies
+import (
+ "context"
+ "strconv"
+ dapr "github.com/dapr/go-sdk/client"
+
+)
+
+//code
+func main() {
+ BINDING_NAME := "checkout";
+ BINDING_OPERATION := "create";
+ orderId := 100
+ client, err := dapr.NewClient()
+ if err != nil {
+ panic(err)
+ }
+ defer client.Close()
+ ctx := context.Background()
+ //Using Dapr SDK to invoke output binding
+ in := &dapr.InvokeBindingRequest{ Name: BINDING_NAME, Operation: BINDING_OPERATION , Data: []byte(strconv.Itoa(orderId))}
+ err = client.InvokeOutputBinding(ctx, in)
+ log.Println("Sending message: " + strconv.Itoa(orderId))
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```javascript
+//dependencies
+import { DaprServer, DaprClient, CommunicationProtocolEnum } from 'dapr-client';
+
+//code
+const daprHost = "127.0.0.1";
+
+var main = function() {
+ var orderId = 100;
+ start(orderId).catch((e) => {
+ console.error(e);
+ process.exit(1);
+ });
+}
+
+async function start(orderId) {
+ const BINDING_NAME = "checkout";
+ const BINDING_OPERATION = "create";
+ const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
+ //Using Dapr SDK to invoke output binding
+ const result = await client.binding.send(BINDING_NAME, BINDING_OPERATION, { orderId: orderId });
+ console.log("Sending message: " + orderId);
+}
+
+main();
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start
+```
+
+{{% /codetab %}}
+
+{{< /tabs >}}
All that's left now is to invoke the output bindings endpoint on a running Dapr instance.
-You can do so using HTTP:
+You can also invoke the output bindings endpoint using HTTP:
```bash
-curl -X POST -H 'Content-Type: application/json' http://localhost:3500/v1.0/bindings/myevent -d '{ "data": { "message": "Hi!" }, "operation": "create" }'
+curl -X POST -H 'Content-Type: application/json' http://localhost:3601/v1.0/bindings/checkout -d '{ "data": { "orderId": "100" }, "operation": "create" }'
```
-As seen above, you invoked the `/binding` endpoint with the name of the binding to invoke, in our case its `myevent`.
+As seen above, you invoked the `/binding` endpoint with the name of the binding to invoke, in our case its `checkout`.
The payload goes inside the mandatory `data` field, and can be any JSON serializable value.
You'll also notice that there's an `operation` field that tells the binding what you need it to do.
You can check [here]({{< ref supported-bindings >}}) which operations are supported for every output binding.
+Watch this [video](https://www.youtube.com/watch?v=ysklxm81MTs&feature=youtu.be&t=1960) on how to use bi-directional output bindings.
+
+
+
+
+
## References
- [Binding API]({{< ref bindings_api.md >}})
diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md
index c0afc13a8..5cf5f1b22 100644
--- a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md
+++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md
@@ -1,7 +1,7 @@
---
type: docs
title: "How-To: Trigger your application with input bindings"
-linkTitle: "How-To: Triggers"
+linkTitle: "How-To: Input bindings"
description: "Use Dapr input bindings to trigger event driven applications"
weight: 200
---
@@ -18,79 +18,265 @@ Dapr bindings allow you to:
For more info on bindings, read [this overview]({{}}).
-For a quickstart sample showing bindings, visit this [link](https://github.com/dapr/quickstarts/tree/master/bindings).
+## Example:
+
+The below code example loosely describes an application that processes orders. In the example, there is an order processing service which has a Dapr sidecar. The checkout service uses Dapr to trigger the application(input binding).
+
+
## 1. Create a binding
-An input binding represents an event resource that Dapr uses to read events from and push to your application.
+An output binding represents a resource that Dapr uses to invoke and send messages to.
-For the purpose of this HowTo, we'll use a Kafka binding. You can find a list of the different binding specs [here]({{< ref supported-bindings >}}).
+For the purpose of this guide, you'll use a Kafka binding. You can find a list of the different binding specs [here]({{< ref setup-bindings >}}).
-Create the following YAML file, named binding.yaml, and save this to a `components` sub-folder in your application directory.
+Create a new binding component with the name of `checkout`.
+
+Inside the `metadata` section, configure Kafka related properties such as the topic to publish the message to and the broker.
+
+{{< tabs "Self-Hosted (CLI)" Kubernetes >}}
+
+{{% codetab %}}
+
+Create the following YAML file, named `binding.yaml`, and save this to a `components` sub-folder in your application directory.
(Use the `--components-path` flag with `dapr run` to point to your custom components dir)
-*Note: When running in Kubernetes, apply this file to your cluster using `kubectl apply -f binding.yaml`*
-
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
- name: myevent
- namespace: default
+ name: checkout
spec:
type: bindings.kafka
version: v1
metadata:
- - name: topics
- value: topic1
+ # Kafka broker connection setting
- name: brokers
value: localhost:9092
+ # consumer configuration: topic and consumer group
+ - name: topics
+ value: sample
- name: consumerGroup
value: group1
+ # publisher configuration: topic
+ - name: publishTopic
+ value: sample
+ - name: authRequired
+ value: "false"
```
-Here, you create a new binding component with the name of `myevent`.
+{{% /codetab %}}
-Inside the `metadata` section, configure the Kafka related properties such as the topics to listen on, the brokers and more.
+{{% codetab %}}
-## 2. Listen for incoming events
+To deploy this into a Kubernetes cluster, fill in the `metadata` connection details of your [desired binding component]({{< ref setup-bindings >}}) in the yaml below (in this case kafka), save as `binding.yaml`, and run `kubectl apply -f binding.yaml`.
-Now configure your application to receive incoming events. If using HTTP, you need to listen on a `POST` endpoint with the name of the binding as specified in `metadata.name` in the file. In this example, this is `myevent`.
-*The following example shows how you would listen for the event in Node.js, but this is applicable to any programming language*
+```yaml
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: checkout
+spec:
+ type: bindings.kafka
+ version: v1
+ metadata:
+ # Kafka broker connection setting
+ - name: brokers
+ value: localhost:9092
+ # consumer configuration: topic and consumer group
+ - name: topics
+ value: sample
+ - name: consumerGroup
+ value: group1
+ # publisher configuration: topic
+ - name: publishTopic
+ value: sample
+ - name: authRequired
+ value: "false"
+```
+
+{{% /codetab %}}
+
+{{< /tabs >}}
+
+## 2. Listen for incoming events(Input Binding)
+
+Now configure your application to receive incoming events. If using HTTP, you need to listen on a `POST` endpoint with the name of the binding as specified in `metadata.name` in the file.
+
+Below are code examples that leverage Dapr SDKs for output binding.
+
+{{< tabs Dotnet Java Python Go Javascript>}}
+
+{{% codetab %}}
+
+```csharp
+//dependencies
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System;
+using Microsoft.AspNetCore.Mvc;
+
+//code
+namespace CheckoutService.controller
+{
+ [ApiController]
+ public class CheckoutServiceController : Controller
+ {
+ [HttpPost("/checkout")]
+ public ActionResult getCheckout([FromBody] int orderId)
+ {
+ Console.WriteLine("Received Message: " + orderId);
+ return "CID" + orderId;
+ }
+ }
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl dotnet run
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```java
+//dependencies
+import reactor.core.publisher.Mono;
+
+//code
+@RestController
+@RequestMapping("/")
+public class CheckoutServiceController {
+ @PostMapping(path = "/checkout")
+ public Mono getCheckout(@RequestBody(required = false) byte[] body) {
+ return Mono.fromRunnable(() ->
+ log.info("Received Message: " + new String(body)));
+ }
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 mvn spring-boot:run
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```python
+#dependencies
+from dapr.ext.grpc import App, BindingRequest
+
+#code
+app = App()
+
+@app.binding('checkout')
+def getCheckout(request: BindingRequest):
+ logging.basicConfig(level = logging.INFO)
+ logging.info('Received Message : ' + request.text())
+
+app.run(6002)
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 -- python3 CheckoutService.py
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
+
+```go
+//dependencies
+import (
+ "encoding/json"
+ "net/http"
+ "github.com/gorilla/mux"
+)
+
+//code
+func getCheckout(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ var orderId int
+ err := json.NewDecoder(r.Body).Decode(&orderId)
+ log.Println("Received Message: ", orderId)
+ if err != nil {
+ log.Printf("error parsing checkout input binding payload: %s", err)
+ w.WriteHeader(http.StatusOK)
+ return
+ }
+}
+
+func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/checkout", getCheckout).Methods("POST", "OPTIONS")
+ http.ListenAndServe(":6002", r)
+}
+
+```
+
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 go run CheckoutService.go
+```
+
+{{% /codetab %}}
+
+{{% codetab %}}
```javascript
-const express = require('express')
-const bodyParser = require('body-parser')
-const app = express()
-app.use(bodyParser.json())
+//dependencies
+import { DaprServer, CommunicationProtocolEnum } from 'dapr-client';
-const port = 3000
+//code
+const daprHost = "127.0.0.1";
+const serverHost = "127.0.0.1";
+const serverPort = "6002";
+const daprPort = "3602";
-app.post('/myevent', (req, res) => {
- console.log(req.body)
- res.status(200).send()
-})
+start().catch((e) => {
+ console.error(e);
+ process.exit(1);
+});
+
+async function start() {
+ const server = new DaprServer(serverHost, serverPort, daprHost, daprPort, CommunicationProtocolEnum.HTTP);
+ await server.binding.receive('checkout', async (orderId) => console.log(`Received Message: ${JSON.stringify(orderId)}`));
+ await server.startServer();
+}
-app.listen(port, () => console.log(`Kafka consumer app listening on port ${port}!`))
```
+Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:
+
+```bash
+dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 dotnet npm start
+```
+
+{{% /codetab %}}
+
+{{< /tabs >}}
+
### ACK-ing an event
In order to tell Dapr that you successfully processed an event in your application, return a `200 OK` response from your HTTP handler.
-```javascript
-res.status(200).send()
-```
-
### Rejecting an event
In order to tell Dapr that the event wasn't processed correctly in your application and schedule it for redelivery, return any response different from `200 OK`. For example, a `500 Error`.
-```javascript
-res.status(500).send()
-```
-
### Specifying a custom route
By default, incoming events will be sent to an HTTP endpoint that corresponds to the name of the input binding.
@@ -108,7 +294,6 @@ spec:
### Event delivery Guarantees
Event delivery guarantees are controlled by the binding implementation. Depending on the binding implementation, the event delivery can be exactly once or at least once.
-
## References
* [Bindings building block]({{< ref bindings >}})
diff --git a/daprdocs/static/images/building-block-bindings-example.png b/daprdocs/static/images/building-block-bindings-example.png
new file mode 100644
index 000000000..4d2f92cc8
Binary files /dev/null and b/daprdocs/static/images/building-block-bindings-example.png differ