Skip to content

Commit 665c299

Browse files
committed
docs(springboot openfeign): add an example to springboot-examples
this example can redirect order request to producer-app. It needs producer-app to run properly. Signed-off-by: lony2003 <zhangke200377@outlook.com>
1 parent 2e7d1d0 commit 665c299

File tree

14 files changed

+541
-4
lines changed

14 files changed

+541
-4
lines changed

sdk-tests/src/test/java/io/dapr/it/spring/feign/PostgreBindingClient.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
import io.dapr.spring.openfeign.annotation.UseDaprClient;
44
import org.springframework.cloud.openfeign.FeignClient;
5+
import org.springframework.web.bind.annotation.PostMapping;
6+
import org.springframework.web.bind.annotation.RequestHeader;
7+
8+
import java.util.List;
59

610
import static io.dapr.it.spring.feign.DaprFeignIT.BINDING_NAME;
711

812
@FeignClient(value = "postgres-binding", url = "http://binding." + BINDING_NAME)
913
@UseDaprClient
1014
public interface PostgreBindingClient {
1115

16+
@PostMapping("/exec")
17+
void exec(@RequestHeader("sql") String sql, @RequestHeader("params") List<String> params);
18+
19+
@PostMapping("/exec")
20+
void exec(@RequestHeader("sql") String sql, @RequestHeader("params") String params);
21+
22+
@PostMapping("/query")
23+
String query(@RequestHeader("sql") String sql, @RequestHeader("params") List<String> params);
1224
}

spring-boot-examples/README.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# Dapr Spring Boot and Testcontainers integration Example
22

3-
This example consists of two applications:
3+
This example consists of three applications:
44
- Producer App:
55
- Publish messages using a Spring Messaging approach
66
- Store and retrieve information using Spring Data CrudRepository
77
- Implements a Workflow with Dapr Workflows
88
- Consumer App:
99
- Subscribe to messages
10+
- OpenFeign App:
11+
- A proxy to Producer App Order API
1012

1113
## Running these examples from source code
1214

@@ -68,6 +70,29 @@ cd consumer-app/
6870
<!-- END_STEP -->
6971
The `consumer-app` starts in port `8081` by default.
7072

73+
And then run in a different terminal:
74+
75+
<!-- STEP
76+
name: Run Demo OpenFeign Service
77+
match_order: none
78+
output_match_mode: substring
79+
expected_stdout_lines:
80+
- 'Started OpenFeignApplication'
81+
background: true
82+
expected_return_code: 143
83+
sleep: 30
84+
timeout_seconds: 45
85+
-->
86+
<!-- Timeout for above service must be more than sleep + timeout for the client-->
87+
88+
```sh
89+
cd openfeign-app/
90+
../../mvnw -Dspring-boot.run.arguments="--reuse=true" spring-boot:test-run
91+
```
92+
93+
<!-- END_STEP -->
94+
The `openfeign-app` starts in port `8083` by default.
95+
7196
## Interacting with the applications
7297

7398
Now that both applications are up you can place an order by sending a POST request to `:8080/orders/`
@@ -92,6 +117,26 @@ curl -X POST localhost:8080/orders -H 'Content-Type: application/json' -d '{ "it
92117

93118
<!-- END_STEP -->
94119

120+
You can also send POST request to the `openfeign-app`, which redirect the request to the `producer-app`:
121+
122+
<!-- STEP
123+
name: Send POST request to Producer App from OpenFeign App
124+
match_order: none
125+
output_match_mode: substring
126+
expected_stdout_lines:
127+
- 'Order Stored and Event Published'
128+
background: true
129+
sleep: 1
130+
timeout_seconds: 2
131+
-->
132+
<!-- Timeout for above service must be more than sleep + timeout for the client-->
133+
134+
```sh
135+
curl -X POST localhost:8083/rpc/producer/orders -H 'Content-Type: application/json' -d '{ "item": "the mars volta EP", "amount": 1 }'
136+
```
137+
138+
<!-- END_STEP -->
139+
95140

96141
If you check the `producer-app` logs you should see the following lines:
97142

spring-boot-examples/kubernetes/README.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Running this example on Kubernetes
22

33
To run this example on Kubernetes, you can use any Kubernetes distribution.
4-
We install Dapr on a Kubernetes cluster and then we will deploy both the `producer-app` and `consumer-app`.
4+
We install Dapr on a Kubernetes cluster and then we will deploy the `producer-app`, `consumer-app` and `openfeign-app`.
55

66
## Creating a cluster and installing Dapr
77

@@ -77,6 +77,24 @@ docker push localhost:5001/sb-consumer-app
7777
podman push localhost:5001/sb-consumer-app --tls-verify=false
7878
```
7979

80+
From inside the `spring-boot-examples/openfeign-app` directory you can run the following command to create a container:
81+
```bash
82+
mvn spring-boot:build-image
83+
```
84+
85+
Once we have the container image created, we need to tag and push to the local registry, so the image can be used from our local cluster.
86+
Alternatively, you can push the images to a public registry and update the Kubernetes manifests accordingly.
87+
88+
```bash
89+
docker tag openfeign-app:0.15.0-SNAPSHOT localhost:5001/sb-openfeign-app
90+
docker push localhost:5001/sb-openfeign-app
91+
```
92+
93+
**Note**: for Podman you need to run:
94+
```
95+
podman push localhost:5001/sb-openfeign-app --tls-verify=false
96+
```
97+
8098
Now we are ready to install our application into the cluster.
8199

82100
## Installing and interacting with the application
@@ -107,7 +125,7 @@ Next you need to use `kubectl port-forward` to be able to send requests to the a
107125
kubectl port-forward svc/producer-app 8080:8080
108126
```
109127

110-
In a different terminals you can check the logs of the `producer-app` and `consumer-app`:
128+
In a different terminals you can check the logs of the `producer-app`, `consumer-app` and `openfeign-app`:
111129

112130
```bash
113131
kubectl logs -f producer-app-<POD_ID>
@@ -117,5 +135,8 @@ and
117135
```bash
118136
kubectl logs -f consumer-app-<POD_ID>
119137
```
138+
and
120139

121-
140+
```bash
141+
kubectl logs -f openfeign-app-<POD_ID>
142+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
labels:
5+
app: openfeign-app
6+
name: openfeign-app
7+
spec:
8+
type: NodePort
9+
ports:
10+
- name: "openfeign-app"
11+
port: 8083
12+
targetPort: 8083
13+
nodePort: 31003
14+
selector:
15+
app: openfeign-app
16+
17+
---
18+
19+
apiVersion: apps/v1
20+
kind: Deployment
21+
metadata:
22+
labels:
23+
app: openfeign-app
24+
name: openfeign-app
25+
spec:
26+
replicas: 1
27+
selector:
28+
matchLabels:
29+
app: openfeign-app
30+
template:
31+
metadata:
32+
annotations:
33+
dapr.io/app-id: openfeign-app
34+
dapr.io/app-port: "8083"
35+
dapr.io/enabled: "true"
36+
labels:
37+
app: openfeign-app
38+
spec:
39+
containers:
40+
- image: localhost:5001/sb-openfeign-app
41+
name: openfeign-app
42+
imagePullPolicy: Always
43+
ports:
44+
- containerPort: 8083
45+
name: openfeign-app
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>io.dapr</groupId>
8+
<artifactId>spring-boot-examples</artifactId>
9+
<version>0.15.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>openfgien-app</artifactId>
13+
<name>openfgien-app</name>
14+
<description>Spring Boot, Testcontainers and Dapr Integration Examples :: OpenFeign App</description>
15+
16+
<properties>
17+
<maven.compiler.source>17</maven.compiler.source>
18+
<maven.compiler.target>17</maven.compiler.target>
19+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20+
</properties>
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-web</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-actuator</artifactId>
30+
</dependency>
31+
<dependency>
32+
<groupId>io.dapr.spring</groupId>
33+
<artifactId>dapr-spring-boot-starter</artifactId>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.springframework.cloud</groupId>
37+
<artifactId>spring-cloud-starter-openfeign</artifactId>
38+
</dependency>
39+
<dependency>
40+
<groupId>io.dapr.spring</groupId>
41+
<artifactId>dapr-spring-openfeign</artifactId>
42+
<version>${dapr.sdk.alpha.version}</version>
43+
</dependency>
44+
<dependency>
45+
<groupId>io.dapr.spring</groupId>
46+
<artifactId>dapr-spring-boot-starter-test</artifactId>
47+
<scope>test</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.testcontainers</groupId>
51+
<artifactId>junit-jupiter</artifactId>
52+
<scope>test</scope>
53+
</dependency>
54+
<dependency>
55+
<groupId>io.rest-assured</groupId>
56+
<artifactId>rest-assured</artifactId>
57+
<scope>test</scope>
58+
</dependency>
59+
</dependencies>
60+
61+
</project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.springboot.examples.openfeign;
15+
16+
import org.springframework.boot.SpringApplication;
17+
import org.springframework.boot.autoconfigure.SpringBootApplication;
18+
import org.springframework.cloud.openfeign.EnableFeignClients;
19+
20+
@SpringBootApplication
21+
@EnableFeignClients
22+
public class OpenFeignApplication {
23+
24+
public static void main(String[] args) {
25+
SpringApplication.run(OpenFeignApplication.class, args);
26+
}
27+
28+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2025 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.springboot.examples.openfeign;
15+
16+
public class Order {
17+
private String id;
18+
private String item;
19+
private Integer amount;
20+
21+
public Order() {
22+
}
23+
24+
public String getId() {
25+
return id;
26+
}
27+
28+
public void setId(String id) {
29+
this.id = id;
30+
}
31+
32+
public String getItem() {
33+
return item;
34+
}
35+
36+
public void setItem(String item) {
37+
this.item = item;
38+
}
39+
40+
public Integer getAmount() {
41+
return amount;
42+
}
43+
44+
public void setAmount(Integer amount) {
45+
this.amount = amount;
46+
}
47+
48+
@Override
49+
public String toString() {
50+
return "Order{" + "id='" + id + '\'' + ", item='" + item + '\'' + ", amount=" + amount + '}';
51+
}
52+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.dapr.springboot.examples.openfeign;
2+
3+
import io.dapr.springboot.examples.openfeign.client.ProducerClient;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.PostMapping;
6+
import org.springframework.web.bind.annotation.RequestBody;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/rpc/producer")
13+
public class ProducerClientRestController {
14+
private final ProducerClient producerClient;
15+
16+
public ProducerClientRestController(ProducerClient producerClient) {
17+
this.producerClient = producerClient;
18+
}
19+
20+
@PostMapping("/orders")
21+
public String storeOrder(@RequestBody Order order) {
22+
return producerClient.storeOrder(order);
23+
}
24+
25+
@GetMapping("/orders")
26+
public Iterable<Order> getAll() {
27+
return producerClient.getAll();
28+
}
29+
30+
@GetMapping("/orders/byItem/")
31+
public Iterable<Order> getAllByItem(@RequestParam("item") String item) {
32+
return producerClient.getAllByItem(item);
33+
}
34+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.dapr.springboot.examples.openfeign.client;
2+
3+
import io.dapr.spring.openfeign.annotation.UseDaprClient;
4+
import io.dapr.springboot.examples.openfeign.Order;
5+
import org.springframework.cloud.openfeign.FeignClient;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestBody;
9+
import org.springframework.web.bind.annotation.RequestParam;
10+
11+
@FeignClient(value = "producer-client", url = "http://method.producer-app/")
12+
@UseDaprClient
13+
public interface ProducerClient {
14+
15+
@PostMapping("/orders")
16+
String storeOrder(@RequestBody Order order);
17+
18+
@GetMapping(value = "/orders", produces = "application/json")
19+
Iterable<Order> getAll();
20+
21+
@GetMapping(value = "/orders/byItem/", produces = "application/json")
22+
Iterable<Order> getAllByItem(@RequestParam("item") String item);
23+
}

0 commit comments

Comments
 (0)