mirror of https://github.com/dapr/quickstarts.git
add java http example
Signed-off-by: Sarthak Sharma <sartsharma@microsoft.com>
This commit is contained in:
parent
e7cfccf383
commit
e40af0acaf
|
@ -0,0 +1,91 @@
|
|||
# Dapr Configuration API
|
||||
|
||||
In this quickstart, you'll create a microservice which makes use of Dapr's Configuration API. Configuration items are key/value pairs containing configuration data such as app ids, partition keys, database names etc. The service gets configuration items from the configuration store and subscribes for configuration updates.
|
||||
|
||||
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/configuration/) link for more information about Dapr and Configuration API.
|
||||
|
||||
> **Note:** This example leverages HTTP `requests` only. If you are looking for the example using the Dapr Client SDK (recommended) [click here](../sdk/).
|
||||
|
||||
This quickstart includes one service:
|
||||
|
||||
- Java service `order-processor`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Maven 3.x](https://maven.apache.org/install.html)
|
||||
- Java JDK 11 (or greater):
|
||||
- [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
|
||||
- [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
|
||||
- [OpenJDK 11](https://jdk.java.net/11/)
|
||||
- Locally running redis instance - a redis instance is automatically created as a docker container when you run `dapr init`
|
||||
- Install Redis CLI - [Getting started with Redis | Redis](https://redis.io/docs/getting-started/). `redis-cli` is installed as part of redis setup
|
||||
|
||||
## Add configuration items to the config store
|
||||
|
||||
- Open a new terminal and set values for config items `orderId1` and `orderId2` using `redis-cli`
|
||||
|
||||
<!-- STEP
|
||||
name: Add configuration items
|
||||
-->
|
||||
|
||||
```bash
|
||||
redis-cli -n 0 MSET orderId1 "101" orderId2 "102"
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
||||
## Build the Java file
|
||||
|
||||
<!-- STEP
|
||||
name: Build Java file
|
||||
-->
|
||||
|
||||
```bash
|
||||
cd ./order-processor
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
||||
## Run order-processor
|
||||
|
||||
1. Navigate to `order-processor` directory.
|
||||
2. Run the service app with Dapr.
|
||||
|
||||
<!-- STEP
|
||||
name: Run order-processor service
|
||||
expected_stdout_lines:
|
||||
- '== APP == Configuration for orderId1:{"orderId1":{"value":"101"}}'
|
||||
- '== APP == Configuration for orderId2:{"orderId2":{"value":"102"}}'
|
||||
- '== APP == App subscribed to config changes with subscription id:'
|
||||
- '= APP == App unsubscribed from config changes'
|
||||
- '== APP == Shutting down spring app'
|
||||
- "Exited App successfully"
|
||||
expected_stderr_lines:
|
||||
output_match_mode: substring
|
||||
match_order: none
|
||||
|
||||
-->
|
||||
|
||||
```bash
|
||||
cd ./order-processor
|
||||
dapr run --app-id order-processor --app-port 6001 --components-path ../../../components -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
||||
## (Optional) Update value of config items
|
||||
|
||||
1. Keep the `order-processor` app running and open a separate terminal
|
||||
2. Change the values of `orderId1` and `orderId2` using `redis-cli`
|
||||
3. `order-processor` app gets the updated values of config items
|
||||
|
||||
<!-- STEP
|
||||
name: Update config items
|
||||
-->
|
||||
|
||||
```bash
|
||||
redis-cli -n 0 MSET orderId1 "103" orderId2 "104"
|
||||
```
|
||||
|
||||
<!--END_STEP -->
|
|
@ -0,0 +1,2 @@
|
|||
include ../../../docker.mk
|
||||
include ../../../validate.mk
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.3</version>
|
||||
<relativePath/>
|
||||
<!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.service</groupId>
|
||||
<artifactId>OrderProcessingService</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>OrderProcessingService</name>
|
||||
<description>Demo for Dapr Configuration API</description>
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20220924</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.22</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.6.4</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,113 @@
|
|||
package com.service;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.json.*;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootApplication
|
||||
public class OrderProcessingServiceApplication {
|
||||
private static final String DAPR_CONFIGURATION_STORE = "configstore";
|
||||
private static List<String> CONFIGURATION_ITEMS = List.of("orderId1",
|
||||
"orderId2");
|
||||
private static String DAPR_HOST = System.getenv().getOrDefault("DAPR_HOST",
|
||||
"http://localhost");
|
||||
private static String DAPR_HTTP_PORT = System.getenv().getOrDefault("DAPR_HTTP_PORT", "3500");
|
||||
private static String APP_PORT = System.getenv().getOrDefault("APP_PORT", "6001");
|
||||
private static final HttpClient httpClient = HttpClient.newBuilder()
|
||||
.version(HttpClient.Version.HTTP_2)
|
||||
.connectTimeout(Duration.ofSeconds(10))
|
||||
.build();
|
||||
|
||||
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
|
||||
URI baseUrl = new URI(DAPR_HOST + ":" + DAPR_HTTP_PORT);
|
||||
// Get config items from the config store
|
||||
try {
|
||||
for (String configurationItem : CONFIGURATION_ITEMS) {
|
||||
URI uri = baseUrl
|
||||
.resolve(
|
||||
"/v1.0-alpha1/configuration/" + DAPR_CONFIGURATION_STORE + "?key=" +
|
||||
configurationItem);
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.GET()
|
||||
.uri(uri)
|
||||
.build();
|
||||
HttpResponse<String> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.ofString());
|
||||
System.out.println("Configuration for " + configurationItem + ":" +
|
||||
response.body());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Could not get config item, err:" + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Create Spring Application to listen to configuration updates
|
||||
SpringApplication app = new SpringApplication(OrderProcessingServiceApplication.class);
|
||||
app.setDefaultProperties(Collections.singletonMap("server.port", APP_PORT));
|
||||
|
||||
// Start the application
|
||||
ConfigurableApplicationContext context = app.run(args);
|
||||
|
||||
// Add delay to allow app channel to be ready
|
||||
Thread.sleep(3000);
|
||||
|
||||
// Subscribe to Configuration Updates
|
||||
String subscriptionId = null;
|
||||
try {
|
||||
URI uri = baseUrl
|
||||
.resolve("/v1.0-alpha1/configuration/" + DAPR_CONFIGURATION_STORE + "/subscribe");
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.GET()
|
||||
.uri(uri)
|
||||
.build();
|
||||
HttpResponse<String> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.ofString());
|
||||
JSONObject subscription = new JSONObject(response.body());
|
||||
subscriptionId = subscription.getString("id");
|
||||
System.out.println("App subscribed to config changes with subscription id:" + subscriptionId);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error subscribing to config updates, err:" + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Receive config updates for 20 seconds, then unsubscribe from config updates and shutdown spring app
|
||||
Thread.sleep(20000);
|
||||
try {
|
||||
// unsubscribe from config updates
|
||||
URI uri = baseUrl
|
||||
.resolve("/v1.0-alpha1/configuration/" + DAPR_CONFIGURATION_STORE + "/" + subscriptionId
|
||||
+ "/unsubscribe");
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.GET()
|
||||
.uri(uri)
|
||||
.build();
|
||||
HttpResponse<String> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.ofString());
|
||||
if (response.body().contains("true")) {
|
||||
|
||||
System.out.println("App unsubscribed from config changes");
|
||||
} else {
|
||||
|
||||
System.out.println("Error unsubscribing from config updates: " + response.body());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error unsubscribing from config updates, err:" + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Shutdown spring app
|
||||
System.out.println("Shutting down spring app");
|
||||
SpringApplication.exit(context, () -> 0);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.service.controller;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class OrderProcessingServiceController {
|
||||
/**
|
||||
* Read configuration updates from config store
|
||||
*
|
||||
* @param body Request body
|
||||
* @return ResponseEntity Returns ResponseEntity.ok()
|
||||
*/
|
||||
@PostMapping(path = "/configuration/configstore/{configItem}", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<?> readUpdates(@RequestBody Map<String, Object> body) {
|
||||
System.out.println("Configuration update "+ body.get("items"));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue