Adding documentation for examples (#153)

This commit is contained in:
Marcos Reyes 2020-01-24 14:36:49 -06:00 committed by Artur Souza
parent 4ba8f4e8d1
commit de1ab57b6c
16 changed files with 561 additions and 133 deletions

View File

@ -3,7 +3,7 @@
* Licensed under the MIT License.
*/
package io.dapr.examples.bindings.http;
package io.dapr.examples.bindings;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -16,10 +16,10 @@ import reactor.core.publisher.Mono;
@RestController
public class InputBindingController {
@PostMapping(path = "/sample123")
@PostMapping(path = "/bindingSample")
public Mono<Void> handleInputBinding(@RequestBody(required = false) byte[] body) {
return Mono.fromRunnable(() ->
System.out.println("Received message through binding: " + (body == null ? "" : new String(body))));
System.out.println("Received message through binding: " + (body == null ? "" : new String(body))));
}
}

View File

@ -3,7 +3,7 @@
* Licensed under the MIT License.
*/
package io.dapr.examples.bindings.http;
package io.dapr.examples.bindings;
import io.dapr.springboot.DaprApplication;
import org.apache.commons.cli.CommandLine;
@ -17,7 +17,7 @@ import org.apache.commons.cli.Options;
* mvn clean install
* 2. cd to [repo-root]/examples
* 3. Run :
* dapr run --app-id inputbinding --app-port 3000 --port 3005 -- mvn exec:java -Dexec.mainClass=io.dapr.examples.bindings.http.InputBindingExample -Dexec.args="-p 3000"
* dapr run --app-id inputbinding --app-port 3000 --port 3005 -- mvn exec:java -D exec.mainClass=io.dapr.examples.bindings.InputBindingExample -D exec.args="-p 3000"
*/
public class InputBindingExample {

View File

@ -3,7 +3,7 @@
* Licensed under the MIT License.
*/
package io.dapr.examples.bindings.http;
package io.dapr.examples.bindings;
import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder;
@ -15,7 +15,7 @@ import io.dapr.serializer.DefaultObjectSerializer;
* mvn clean install
* 2. cd to [repo-root]/examples
* 3. Run the program:
* dapr run --app-id outputbinding --port 3006 -- mvn exec:java -Dexec.mainClass=io.dapr.examples.bindings.http.OutputBindingExample
* dapr run --app-id outputbinding --port 3006 -- mvn exec:java -D exec.mainClass=io.dapr.examples.bindings.OutputBindingExample
*/
public class OutputBindingExample {
@ -27,20 +27,20 @@ public class OutputBindingExample {
public static void main(String[] args) {
DaprClient client = new DaprClientBuilder(new DefaultObjectSerializer(), new DefaultObjectSerializer()).build();
final String BINDING_NAME = "sample123";
final String BINDING_NAME = "bindingSample";
// This is an example of sending data in a user-defined object. The input binding will receive:
// {"message":"hello"}
MyClass myClass = new MyClass();
myClass.message = "hello";
System.out.println("sending first message");
System.out.println("sending a class with message: " + myClass.message);
client.invokeBinding(BINDING_NAME, myClass).block();
// This is an example of sending a plain string. The input binding will receive
// cat
// This is an example of sending a plain string. The input binding will receive:
// "cat"
final String m = "cat";
System.out.println("sending " + m);
System.out.println("sending a plain string: " + m);
client.invokeBinding(BINDING_NAME, m).block();
try {

View File

@ -0,0 +1,142 @@
# Dapr Bindings Sample
In this sample, we'll create two java applications: an output binding application and an input binding application, using Dapr Java SDK.
This sample includes two applications:
* InputBindingExample (Initializes the Dapr Spring boot application client)
* OutputBindingExample (pushes the event message)
Visit [this](https://github.com/dapr/docs/tree/master/concepts/bindings) link for more information about Dapr and bindings concepts.
## Binding sample using the Java-SDK
In this example, the component used is Kafka but others are also available.
Visit [this](https://github.com/dapr/components-contrib/tree/master/bindings) link for more information about binding implementations.
## Pre-requisites
* [Dapr and Dapr Cli](https://github.com/dapr/docs/blob/master/getting-started/environment-setup.md#environment-setup).
* Java JDK 11 (or greater): [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11) or [OpenJDK](https://jdk.java.net/13/).
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
### Checking out the code
Clone this repository:
```sh
git clone https://github.com/dapr/java-sdk.git
cd java-sdk
```
Then build the Maven project:
```sh
# make sure you are in the `java-sdk` directory.
mvn install
```
### Setting Kafka locally
Before getting into the application code, follow these steps in order to setup a local instance of Kafka. This is needed for the local instances. Steps are:
1. navigate to the [repo-root]/examples/src/main/java/io/dapr/examples/bindings
2. Run `docker-compose -f ./docker-compose-single-kafka.yml up -d` to run the container locally
3. Run `docker ps` to see the container running locally:
```bash
342d3522ca14 kafka-docker_kafka "start-kafka.sh" 14 hours ago Up About
a minute 0.0.0.0:9092->9092/tcp kafka-docker_kafka_1
0cd69dbe5e65 wurstmeister/zookeeper "/bin/sh -c '/usr/sb…" 8 days ago Up About
a minute 22/tcp, 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp kafka-docker_zookeeper_1
```
Click [here](https://github.com/wurstmeister/kafka-docker) for more information about the kafka broker server.
### Running the Input binding sample
The input binding sample uses the Spring Boot´s DaprApplication class for initializing the `InputBindingController`. In `InputBindingExample.java` file, you will find the `InputBindingExample` class and the `main` method. See the code snippet below:
```java
public class InputBindingExample {
public static void main(String[] args) throws Exception {
///..
// If port string is not valid, it will throw an exception.
int port = Integer.parseInt(cmd.getOptionValue("port"));
// Start Dapr's callback endpoint.
DaprApplication.start(port);
}
///...
}
```
`DaprApplication.start()` Method will run an Spring Boot application that registers the `InputBindingController`, which exposes the actual handling of the event message as a POST request. The Dapr's sidecar is the one that performs the actual call to this controller, based on the binding features and the output binding action.
```java
@RestController
public class InputBindingController {
@PostMapping(path = "/bindingSample")
public Mono<Void> handleInputBinding(@RequestBody(required = false) byte[] body) {
return Mono.fromRunnable(() ->
System.out.println("Received message through binding: " + (body == null ? "" : new String(body))));
}
}
```
Execute the follow script in order to run the Input Binding example:
```sh
cd to [repo-root]/examples
dapr run --app-id inputbinding --app-port 3000 --port 3005 -- mvn exec:java -D exec.mainClass=io.dapr.examples.bindings.InputBindingExample -D exec.args="-p 3000"
```
### Running the Output binding sample
The output binding application is a simple java class with a main method that uses the Dapr Client to invoke binding.
In the `OutputBindingExample.java` file, you will find the `OutputBindingExample` class, containing the main method. The main method declares a Dapr Client using the `DaprClientBuilder` class. Notice that this builder gets two serializer implementations in the constructor: One is for Dapr's sent and recieved objects, and second is for objects to be persisted. The client publishes events using `invokeBinding` method. See the code snippet below:
```java
public class OutputBindingExample {
///...
public static void main(String[] args) throws Exception {
DaprClient client = new DaprClientBuilder(new DefaultObjectSerializer(), new DefaultObjectSerializer()).build();
final String BINDING_NAME = "bindingSample";
///...
MyClass myClass = new MyClass();
myClass.message = "hello";
System.out.println("sending an object instance with message: " + myClass.message);
client.invokeBinding(BINDING_NAME, myClass); //Binding a data object
///..
final String m = "cat";
System.out.println("sending a plain string: " + m);
client.invokeBinding(BINDING_NAME, m); //Binding a plain string text
}
///...
}
```
This example binds two events: A user-defined data object (using the `myClass` object as parameter) and a simple string using the same `invokeBinding` method.
Use the follow command to execute the Output Binding example:
```sh
cd to [repo-root]/examples
dapr run --app-id outputbinding --port 3006 -- mvn exec:java -D exec.mainClass=io.dapr.examples.bindings.OutputBindingExample
```
Once running, the OutputBindingExample should print the output as follows:
![publisheroutput](../../../../../resources/img/outputbinding.png)
Events have been sent.
Once running, the InputBindingExample should print the output as follows:
![publisheroutput](../../../../../resources/img/inputbinding.png)
Events have been retrieved from the binding.
For more details on Dapr Spring Boot integration, please refer to [Dapr Spring Boot](../../springboot/DaprApplication.java) Application implementation.

View File

@ -0,0 +1,14 @@
version: '2'
services:
zookeeper:
image: wurstmeister/zookeeper:latest
ports:
- "2181:2181"
kafka:
image: wurstmeister/kafka:latest
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1
KAFKA_CREATE_TOPICS: "sample:1:1"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181

View File

@ -15,7 +15,7 @@ import org.apache.commons.cli.Options;
* 1. Build and install jars:
* mvn clean install
* 2. Run in server mode:
* dapr run --app-id invokedemo --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -Dexec.mainClass=io.dapr.examples.invoke.http.DemoService -Dexec.args="-p 3000"
* dapr run --app-id invokedemo --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.invoke.http.DemoService -D exec.args="-p 3000"
*/
public class DemoService {

View File

@ -0,0 +1,130 @@
# Method invocation Sample
In this sample, we'll create a two java applications: An exposer service application which exposes a method and a client application which will invoke the method from demo service using Dapr.
This sample includes:
* DemoService (Exposes the method to be remotely accessed)
* InvokeClient (Invokes the exposed method from DemoService)
Visit [this](https://github.com/dapr/docs/blob/master/concepts/service-invocation/service-invocation.md) link for more information about Dapr and service invocation.
## Remote invocation using the Java-SDK
This sample uses the Client provided in Dapr Java SDK invoking a remote method. Exposing the method
## Pre-requisites
* [Dapr and Dapr Cli](https://github.com/dapr/docs/blob/master/getting-started/environment-setup.md#environment-setup).
* Java JDK 11 (or greater): [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11) or [OpenJDK](https://jdk.java.net/13/).
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
### Checking out the code
Clone this repository:
```sh
git clone https://github.com/dapr/java-sdk.git
cd java-sdk
```
Then build the Maven project:
```sh
# make sure you are in the `java-sdk` directory.
mvn install
```
### Running the Demo service sample
The Demo service application is meant to expose a method that can be remotely invoked. In this example, the exposer feature has two parts:
In the `DemoService.java` file, you will find the `DemoService` class, containing the main method. The main method uses the Spring Boot´s DaprApplication class for initializing the `ExposerServiceController`. See the code snippet below:
```java
public class DemoService {
///...
public static void main(String[] args) throws Exception {
///...
// If port string is not valid, it will throw an exception.
int port = Integer.parseInt(cmd.getOptionValue("port"));
DaprApplication.start(port);
}
}
```
`DaprApplication.start()` Method will run an Spring Boot application that registers the `DemoServiceController`, which exposes the invoking action as a POST request. The Dapr's sidecar is the one that performs the actual call to the controller, based on the binding features and the remote invocation action.
This Spring Controller exposes the `say` method. The method retrieves metadata from the headers and prints them along with the current date in console. The actual response from method is the formatted current date. See the code snippet below:
```java
@RestController
public class DemoServiceController {
///...
@PostMapping(path = "/say")
public Mono<String> handleMethod(@RequestBody(required = false) byte[] body,
@RequestHeader Map<String, String> headers) {
return Mono.fromSupplier(() -> {
try {
String message = body == null ? "" : new String(body, StandardCharsets.UTF_8);
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
String utcNowAsString = DATE_FORMAT.format(utcNow.getTime());
String metadataString = headers == null ? "" : OBJECT_MAPPER.writeValueAsString(headers);
// Handles the request by printing message.
System.out.println(
"Server: " + message + " @ " + utcNowAsString + " and metadata: " + metadataString);
return utcNowAsString;
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
```
Use the follow command to execute the exposer example:
```sh
dapr run --app-id invokedemo --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.invoke.http.DemoService -D exec.args="-p 3000"
```
Once running, the ExposerService is now ready to be invoked by Dapr.
### Running the InvokeClient sample
The Invoke client sample uses the Dapr SDK for invoking the remote method. The main method declares a Dapr Client using the DaprClientBuilder class. Notice that this builder gets two serializer implementations in the constructor: One is for Dapr's sent and recieved objects, and second is for objects to be persisted. It needs to know the method name to invoke as well as the application id for the remote application. In `InvokeClient.java` file, you will find the `InvokeClient` class and the `main` method. See the code snippet below:
```java
public class InvokeClient {
private static final String SERVICE_APP_ID = "invokedemo";
///...
public static void main(String[] args) {
DaprClient client = (new DaprClientBuilder(new DefaultObjectSerializer(), new DefaultObjectSerializer())).build();
for (String message : args) {
client.invokeService(Verb.POST, SERVICE_APP_ID, "say", message, null, String.class).block();
}
}
///...
}
```
The class knows the app id for the remote application. It uses the the static `Dapr.getInstance().invokeService` method to invoke the remote method defining the parameters: The verb, application id, method name, and proper data and metadata, as well as the type of the expected retun data.
Execute the follow script in order to run the InvokeClient example, passing two messages for the remote method:
```sh
dapr run --port 3006 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.invoke.http.InvokeClient -D exec.args="'message one' 'message two'"
```
Once running, the output should display the messages sent from invoker in the exposer service output as follows:
![exposeroutput](../../../../../../resources/img/exposer-service.png)
Method have been remotely invoked and displaying the remote messages.
For more details on Dapr Spring Boot integration, please refer to [Dapr Spring Boot](../../../springboot/DaprApplication.java) Application implementation.

View File

@ -16,18 +16,21 @@ import java.util.Collections;
* 1. Build and install jars:
* mvn clean install
* 2. Run the program:
* dapr run --app-id publisher --port 3006 -- mvn exec:java -pl=examples -Dexec.mainClass=io.dapr.examples.pubsub.http.Publisher
* dapr run --app-id publisher --port 3006 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.pubsub.http.Publisher
*/
public class Publisher {
//Number of messages to be sent: 10
private static final int NUM_MESSAGES = 10;
private static final String TOPIC_NAME = "message";
//The title of the topic to be used for publishing
private static final String TOPIC_NAME = "testingtopic";
public static void main(String[] args) throws Exception {
//Creating the DaprClient: Using the default builder client produces an HTTP Dapr Client
DaprClient client = new DaprClientBuilder(new DefaultObjectSerializer(), new DefaultObjectSerializer()).build();
for (int i = 0; i < NUM_MESSAGES; i++) {
String message = String.format("This is message #%d", i);
//Publishing messages
client.publishEvent(TOPIC_NAME, message).block();
System.out.println("Published message: " + message);
@ -40,10 +43,11 @@ public class Publisher {
}
}
//Publishing a single bite: Example of non-string based content published
client.publishEvent(
TOPIC_NAME,
new byte[] { 1 },
Collections.singletonMap("content-type", "application/octet-stream")).block();
TOPIC_NAME,
new byte[] { 1 },
Collections.singletonMap("content-type", "application/octet-stream")).block();
System.out.println("Published one byte.");
System.out.println("Done.");

View File

@ -0,0 +1,140 @@
# Dapr Pub-Sub Sample
In this sample, we'll create a publisher and a subscriber java applications using Dapr, based on the publish-subcribe pattern. The publisher will generate messages of a specific topic, while subscriber will listen for messages of specific topic. See [Why Pub-Sub](#why-pub-sub) to understand when this pattern might be a good choice for your software architecture.
Visit [this](https://github.com/dapr/docs/tree/master/concepts/publish-subscribe-messaging) link for more information about Dapr and Pub-Sub.
## Pub-Sub Sample using the Java-SDK
This sample uses the HTTP Client provided in Dapr Java SDK for subscribing, and Dapr Spring Boot integration for publishing. This example uses Redis Streams (enabled in Redis versions => 5).
## Pre-requisites
* [Dapr and Dapr Cli](https://github.com/dapr/docs/blob/master/getting-started/environment-setup.md#environment-setup).
* Java JDK 11 (or greater): [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11) or [OpenJDK](https://jdk.java.net/13/).
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
### Checking out the code
Clone this repository:
```sh
git clone https://github.com/dapr/java-sdk.git
cd java-sdk
```
Then build the Maven project:
```sh
# make sure you are in the `java-sdk` directory.
mvn install
```
### Running the subscriber
The first is the subscriber. It will subscribe to the topic to be used by the publisher and read the messages published. The Subscriber uses the Spring Boot´s DaprApplication class for initializing the `SubscriberController`. In `Subscriber.java` file, you will find the `Subscriber` class and the `main` method. See the code snippet below:
```java
public class Subscriber {
public static void main(String[] args) throws Exception {
///...
// Start Dapr's callback endpoint.
DaprApplication.start(port);
}
}
```
`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:
```java
@RestController
public class SubscriberController {
///...
@GetMapping("/dapr/subscribe")
public byte[] daprConfig() throws Exception {
return SERIALIZER.serialize(new String[] { "message" });
}
@PostMapping(path = "/message")
public Mono<Void> handleMessage(@RequestBody(required = false) byte[] body,
@RequestHeader Map<String, String> headers) {
return Mono.fromRunnable(() -> {
try {
// Dapr's event is compliant to CloudEvent.
CloudEventEnvelope envelope = SERIALIZER.deserialize(body, CloudEventEnvelope.class);
String message = envelope.getData() == null ? "" : new String(envelope.getData());
System.out.println("Subscriber got message: " + message);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
```
Execute the follow script in order to run the Subscriber example:
```sh
dapr run --app-id subscriber --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.pubsub.http.Subscriber -D exec.args="-p 3000"
```
### Running the publisher
The other component is the publisher. It is a simple java application with a main method that uses the Dapr HTTP Client to publish 10 messages to an specific topic.
In the `Publisher.java` file, you will find the `Publisher` class, containing the main method. The main method declares a Dapr Client using the `DaprClientBuilder` class. Notice that this builder gets two serializer implementations in the constructor: One is for Dapr's sent and recieved objects, and second is for objects to be persisted. The client publishes messages using `publishEvent` method. See the code snippet below:
```java
public class Publisher {
private static final int NUM_MESSAGES = 10;
private static final String TOPIC_NAME = "testingtopic";
///...
public static void main(String[] args) throws Exception {
DaprClient client = new DaprClientBuilder(new DefaultObjectSerializer(), new DefaultObjectSerializer()).build();
for (int i = 0; i < NUM_MESSAGES; i++) {
String message = String.format("This is message #%d", i);
client.publishEvent(TOPIC_NAME, message).block();
System.out.println("Published message: " + message);
//..
}
}
///...
}
```
This example also pushes a non-string content event, the follow code in same `Publisher` main method publishes a bite:
```java
public class Publisher {
///...
public static void main(String[] args) throws Exception {
///...
//Publishing a single bite: Example of non-string based content published
client.publishEvent(
TOPIC_NAME,
new byte[] { 1 },
Collections.singletonMap("content-type", "application/octet-stream")).block();
System.out.println("Published one byte.");
System.out.println("Done.");
}
///...
}
```
Use the follow command to execute the Publisher example:
```sh
dapr run --app-id publisher --port 3006 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.pubsub.http.Publisher
```
Once running, the Publisher should print the output as follows:
![publisheroutput](../../../../../../resources/img/publisher.png)
Messages have been published in the topic.
Once running, the Subscriber should print the output as follows:
![publisheroutput](../../../../../../resources/img/subscriber.png)
Messages have been retrieved from the topic.
For more details on Dapr Spring Boot integration, please refer to [Dapr Spring Boot](../../../springboot/DaprApplication.java) Application implementation.

View File

@ -10,7 +10,6 @@ import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Service for subscriber.
@ -19,7 +18,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* 2. Run the server:
* dapr run --app-id subscriber --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -Dexec.mainClass=io.dapr.examples.pubsub.http.Subscriber -Dexec.args="-p 3000"
*/
@SpringBootApplication
public class Subscriber {
public static void main(String[] args) throws Exception {

View File

@ -5,8 +5,8 @@
package io.dapr.examples.pubsub.http;
import io.dapr.serializer.DefaultObjectSerializer;
import io.dapr.client.domain.CloudEvent;
import io.dapr.serializer.DefaultObjectSerializer;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
@ -21,16 +21,16 @@ public class SubscriberController {
/**
* Dapr's default serializer/deserializer.
*/
private static final DefaultObjectSerializer SERIALIZER = new DefaultObjectSerializer();
private static final DefaultObjectSerializer SERIALIZER = new DefaultObjectSerializer ();
@GetMapping("/dapr/subscribe")
public byte[] daprConfig() throws Exception {
return SERIALIZER.serialize(new String[] { "message" });
return SERIALIZER.serialize(new String[] { "testingtopic" });
}
@PostMapping(path = "/message")
@PostMapping(path = "/testingtopic")
public Mono<Void> handleMessage(@RequestBody(required = false) byte[] body,
@RequestHeader Map<String, String> headers) {
@RequestHeader Map<String, String> headers) {
return Mono.fromRunnable(() -> {
try {
// Dapr's event is compliant to CloudEvent.

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB