Skip to content

Commit eb36727

Browse files
committed
Added gRPC example
1 parent f8f1473 commit eb36727

File tree

11 files changed

+276
-8
lines changed

11 files changed

+276
-8
lines changed

ftgo-end-to-end-tests/src/test/java/net/chrisrichardson/ftgo/endtoendtests/EndToEndTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private void reviseOrder(int orderId) {
145145
body(new ReviseOrderRequest(Collections.singletonMap(CHICKED_VINDALOO_MENU_ITEM_ID, revisedQuantityOfChickenVindaloo)))
146146
.contentType("application/json").
147147
when().
148-
put(orderBaseUrl(Integer.toString(orderId))).
148+
post(orderBaseUrl(Integer.toString(orderId), "revise")).
149149
then().
150150
statusCode(200);
151151
}

ftgo-order-service/build.gradle

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ buildscript {
1111
classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"
1212
classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:2.0.0.M7"
1313
classpath "com.avast.gradle:gradle-docker-compose-plugin:$dockerComposePluginVersion"
14+
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
1415
}
1516
}
1617

1718
apply plugin: 'org.springframework.boot'
1819
apply plugin: "io.spring.dependency-management"
1920
apply plugin: 'spring-cloud-contract'
2021
apply plugin: 'docker-compose'
22+
apply plugin: 'com.google.protobuf'
2123

2224
apply plugin: IntegrationTestsPlugin
2325
apply plugin: ComponentTestsPlugin
@@ -69,13 +71,37 @@ dockerCompose {
6971
componentTest.dependsOn(componentTestsComposeUp)
7072
integrationTest.dependsOn(integrationTestsComposeUp)
7173

72-
repositories {
73-
maven {
74-
url 'http://oss.jfrog.org/oss-snapshot-local/'
74+
protobuf {
75+
protoc {
76+
// Download from repositories
77+
artifact = 'com.google.protobuf:protoc:3.0.0'
7578
}
79+
plugins {
80+
grpc {
81+
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
82+
}
83+
}
84+
generateProtoTasks {
85+
all()*.plugins {
86+
grpc {
87+
// To generate deprecated interfaces and static bindService method,
88+
// turn the enable_deprecated option to true below:
89+
option 'enable_deprecated=false'
90+
}
91+
}
92+
}
93+
}
7694

95+
apply plugin: 'idea'
96+
97+
idea {
98+
module {
99+
sourceDirs += file("${projectDir}/build/generated/source/proto/main/java");
100+
sourceDirs += file("${projectDir}/build/generated/source/proto/main/grpc");
101+
}
77102
}
78103

104+
79105
dependencies {
80106

81107

@@ -103,6 +129,10 @@ dependencies {
103129
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
104130
compile 'javax.el:javax.el-api:2.2.5'
105131

132+
compile "io.grpc:grpc-netty:${grpcVersion}"
133+
compile "io.grpc:grpc-protobuf:${grpcVersion}"
134+
compile "io.grpc:grpc-stub:${grpcVersion}"
135+
106136
testCompile "io.eventuate.util:eventuate-util-test:$eventuateUtilVersion"
107137
testCompile "io.eventuate.tram.core:eventuate-tram-test-util:$eventuateTramVersion"
108138

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package net.chrisrichardson.ftgo.orderservice.grpc;
2+
3+
4+
import io.grpc.*;
5+
6+
import java.util.List;
7+
import java.util.concurrent.TimeUnit;
8+
import java.util.logging.Logger;
9+
import java.util.stream.IntStream;
10+
11+
import net.chrisrichardson.ftgo.orderservice.web.MenuItemIdAndQuantity;
12+
13+
public class OrderServiceClient {
14+
private static final Logger logger = Logger.getLogger(OrderServiceClient.class.getName());
15+
16+
private final ManagedChannel channel;
17+
private final OrderServiceGrpc.OrderServiceBlockingStub clientStub;
18+
19+
public OrderServiceClient(String host, int port) {
20+
channel = ManagedChannelBuilder.forAddress(host, port)
21+
.usePlaintext()
22+
.build();
23+
clientStub = OrderServiceGrpc.newBlockingStub(channel);
24+
}
25+
26+
public void shutdown() throws InterruptedException {
27+
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
28+
}
29+
30+
public long createOrder(long consumerId, long restaurantId, List<MenuItemIdAndQuantity> lineItems) {
31+
CreateOrderRequest.Builder builder = CreateOrderRequest.newBuilder()
32+
.setConsumerId(consumerId)
33+
.setRestaurantId(restaurantId);
34+
CreateOrderRequest request = builder
35+
.build();
36+
IntStream.range(0, lineItems.size()).forEach(idx -> {
37+
MenuItemIdAndQuantity li = lineItems.get(idx);
38+
builder.setLineItems(idx, LineItem.newBuilder().setQuantity(li.getQuantity()).setMenuItemId(li.getMenuItemId()).build());
39+
});
40+
CreateOrderReply response;
41+
response = clientStub.createOrder(request);
42+
return response.getOrderId();
43+
}
44+
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package net.chrisrichardson.ftgo.orderservice.grpc;
2+
3+
4+
import net.chrisrichardson.ftgo.orderservice.domain.Order;
5+
import net.chrisrichardson.ftgo.orderservice.domain.OrderJpaTestConfiguration;
6+
import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.test.context.SpringBootTest;
11+
import org.springframework.test.context.junit4.SpringRunner;
12+
13+
import java.util.Collections;
14+
15+
import static org.junit.Assert.assertEquals;
16+
import static org.mockito.Mockito.when;
17+
18+
@RunWith(SpringRunner.class)
19+
@SpringBootTest(classes = OrderServiceGrpIntegrationTestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
20+
public class OrderServiceGrpIntegrationTest {
21+
22+
@Autowired
23+
private OrderService orderService;
24+
25+
@Test
26+
public void shouldCreateOrder() {
27+
28+
Order order = new Order(1, 2, Collections.emptyList());
29+
order.setId(101L);
30+
31+
when(orderService.createOrder(1, 2, Collections.emptyList())).thenReturn(order);
32+
OrderServiceClient client = new OrderServiceClient("localhost", 50051);
33+
34+
long orderId = client.createOrder(1, 2, Collections.emptyList());
35+
36+
assertEquals(101L, orderId);
37+
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package net.chrisrichardson.ftgo.orderservice.grpc;
2+
3+
import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.context.annotation.Import;
7+
8+
import static org.mockito.Mockito.mock;
9+
10+
@Configuration
11+
@Import(GrpcConfiguration.class)
12+
public class OrderServiceGrpIntegrationTestConfiguration {
13+
14+
@Bean
15+
public OrderService orderService() {
16+
return mock(OrderService.class);
17+
}
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.chrisrichardson.ftgo.orderservice.grpc;
2+
3+
import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
public class GrpcConfiguration {
9+
10+
@Bean
11+
public OrderServiceServer helloWorldServer(OrderService orderService) {
12+
return new OrderServiceServer(orderService);
13+
}
14+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package net.chrisrichardson.ftgo.orderservice.grpc;
2+
3+
import io.grpc.Server;
4+
import io.grpc.ServerBuilder;
5+
import io.grpc.stub.StreamObserver;
6+
import net.chrisrichardson.ftgo.orderservice.domain.Order;
7+
import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
8+
import net.chrisrichardson.ftgo.orderservice.web.MenuItemIdAndQuantity;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import javax.annotation.PostConstruct;
13+
import javax.annotation.PreDestroy;
14+
import java.io.IOException;
15+
16+
import static java.util.stream.Collectors.toList;
17+
18+
public class OrderServiceServer {
19+
private static final Logger logger = LoggerFactory.getLogger(OrderServiceServer.class);
20+
21+
private int port = 50051;
22+
private Server server;
23+
private OrderService orderService;
24+
25+
public OrderServiceServer(OrderService orderService) {
26+
this.orderService = orderService;
27+
}
28+
29+
@PostConstruct
30+
public void start() throws IOException {
31+
server = ServerBuilder.forPort(port)
32+
.addService(new OrderServiceImpl())
33+
.build()
34+
.start();
35+
logger.info("Server started, listening on " + port);
36+
}
37+
38+
@PreDestroy
39+
public void stop() {
40+
if (server != null) {
41+
logger.info("*** shutting down gRPC server since JVM is shutting down");
42+
server.shutdown();
43+
logger.info("*** server shut down");
44+
}
45+
}
46+
47+
48+
private class OrderServiceImpl extends OrderServiceGrpc.OrderServiceImplBase {
49+
50+
@Override
51+
public void createOrder(CreateOrderRequest req, StreamObserver<CreateOrderReply> responseObserver) {
52+
Order order = orderService.createOrder(req.getConsumerId(),
53+
req.getRestaurantId(),
54+
req.getLineItemsList().stream().map(x -> new MenuItemIdAndQuantity(x.getMenuItemId(), x.getQuantity())).collect(toList())
55+
);
56+
CreateOrderReply reply = CreateOrderReply.newBuilder().setOrderId(order.getId()).build();
57+
responseObserver.onNext(reply);
58+
responseObserver.onCompleted();
59+
}
60+
61+
@Override
62+
public void cancelOrder(CancelOrderRequest req, StreamObserver<CancelOrderReply> responseObserver) {
63+
CancelOrderReply reply = CancelOrderReply.newBuilder().setMessage("Hello " + req.getName()).build();
64+
responseObserver.onNext(reply);
65+
responseObserver.onCompleted();
66+
}
67+
68+
@Override
69+
public void reviseOrder(ReviseOrderRequest req, StreamObserver<ReviseOrderReply> responseObserver) {
70+
ReviseOrderReply reply = ReviseOrderReply.newBuilder().setMessage("Hello " + req.getName()).build();
71+
responseObserver.onNext(reply);
72+
responseObserver.onCompleted();
73+
}
74+
}
75+
}

ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/main/OrderServiceMain.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.eventuate.tram.commands.common.ChannelMapping;
55
import io.eventuate.tram.commands.common.DefaultChannelMapping;
66
import net.chrisrichardson.eventstore.examples.customersandorders.commonswagger.CommonSwaggerConfiguration;
7+
import net.chrisrichardson.ftgo.orderservice.grpc.GrpcConfiguration;
78
import net.chrisrichardson.ftgo.orderservice.messaging.OrderServiceMessagingConfiguration;
89
import net.chrisrichardson.ftgo.orderservice.service.OrderCommandHandlersConfiguration;
910
import net.chrisrichardson.ftgo.orderservice.web.OrderWebConfiguration;
@@ -14,7 +15,7 @@
1415

1516
@SpringBootApplication
1617
@Import({OrderWebConfiguration.class, OrderCommandHandlersConfiguration.class, OrderServiceMessagingConfiguration.class,
17-
TramJdbcKafkaConfiguration.class, CommonSwaggerConfiguration.class})
18+
TramJdbcKafkaConfiguration.class, CommonSwaggerConfiguration.class, GrpcConfiguration.class})
1819
public class OrderServiceMain {
1920

2021
@Bean

ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/web/OrderController.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ public ResponseEntity<GetOrderResponse> cancel(@PathVariable long orderId) {
6060
}
6161
}
6262

63-
// TODO implement revise order endpoint
64-
65-
@RequestMapping(path = "/{orderId}", method = RequestMethod.PUT)
63+
@RequestMapping(path = "/{orderId}/revise", method = RequestMethod.POST)
6664
public ResponseEntity<GetOrderResponse> revise(@PathVariable long orderId, @RequestBody ReviseOrderRequest request) {
6765
try {
6866
Order order = orderService.reviseOrder(orderId, new OrderRevision(Optional.empty(), request.getRevisedLineItemQuantities()));
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
syntax = "proto3";
2+
3+
option java_multiple_files = true;
4+
option java_package = "net.chrisrichardson.ftgo.orderservice.grpc";
5+
option java_outer_classname = "OrderServiceProto";
6+
option objc_class_prefix = "OS";
7+
8+
package orderservice;
9+
10+
service OrderService {
11+
rpc createOrder(CreateOrderRequest) returns (CreateOrderReply) {}
12+
rpc cancelOrder(CancelOrderRequest) returns (CancelOrderReply) {}
13+
rpc reviseOrder(ReviseOrderRequest) returns (ReviseOrderReply) {}
14+
}
15+
16+
message CreateOrderRequest {
17+
int64 restaurantId = 1;
18+
int64 consumerId = 2;
19+
repeated LineItem lineItems = 3;
20+
}
21+
22+
message LineItem {
23+
string menuItemId = 1;
24+
int32 quantity = 2;
25+
}
26+
27+
28+
message CreateOrderReply {
29+
int64 orderId = 1;
30+
}
31+
32+
message CancelOrderRequest {
33+
string name = 1;
34+
}
35+
36+
message CancelOrderReply {
37+
string message = 1;
38+
}
39+
40+
message ReviseOrderRequest {
41+
string name = 1;
42+
}
43+
44+
message ReviseOrderReply {
45+
string message = 1;
46+
}

0 commit comments

Comments
 (0)