BAEL-7141: Create project structure with API stubs, service provider and service consumer. (#15478)

This commit is contained in:
Ralf Ueberfuhr 2024-01-05 10:37:23 +01:00 committed by GitHub
parent ff11a92e8a
commit b4bbc940ad
14 changed files with 393 additions and 0 deletions

View File

@ -91,6 +91,7 @@
<module>spring-boot-cassandre</module>
<module>spring-boot-react</module>
<!-- <module>spring-boot-3</module> --> <!-- JAVA-20931 -->
<module>spring-boot-3-grpc</module>
<module>spring-boot-3-native</module>
<module>spring-boot-3-observation</module>
<module>spring-boot-3-test-pitfalls</module>

View File

@ -0,0 +1,35 @@
<?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>
<artifactId>helloworld-grpc-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloworld-grpc-consumer</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../../parent-boot-3</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>${grpc-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>helloworld-grpc-java</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
<spring-boot.version>3.2.0</spring-boot.version>
<grpc-spring-boot-starter.version>2.15.0.RELEASE</grpc-spring-boot-starter.version>
</properties>
</project>

View File

@ -0,0 +1,61 @@
package com.baeldung.helloworld.consumer;
import com.baeldung.helloworld.stubs.HelloWorldRequest;
import com.baeldung.helloworld.stubs.HelloWorldResponse;
import com.baeldung.helloworld.stubs.HelloWorldServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.stream.Stream;
@Component
public class HelloWorldClient {
private static final Logger log = LoggerFactory.getLogger(HelloWorldClient.class);
// constructor injection not possible
// "Do not use in conjunction with @Autowired or @Inject"
// (see https://github.com/grpc-ecosystem/grpc-spring)
@GrpcClient("hello")
HelloWorldServiceGrpc.HelloWorldServiceStub stub;
@EventListener(ContextRefreshedEvent.class)
void sendRequests() {
// prepare the response callback
final StreamObserver<HelloWorldResponse> responseObserver = new StreamObserver<HelloWorldResponse>() {
@Override
public void onNext(HelloWorldResponse helloWorldResponse) {
log.info("Hello World Response: {}", helloWorldResponse.getGreeting());
}
@Override
public void onError(Throwable throwable) {
log.error("Error occured", throwable);
}
@Override
public void onCompleted() {
log.info("Hello World request finished");
}
};
// connect to the server
final StreamObserver<HelloWorldRequest> request = stub.sayHello(responseObserver);
// send multiple requests (streaming)
Stream.of("Tom", "Julia", "Baeldung", "", "Ralf")
.map(HelloWorldRequest.newBuilder()::setName)
.map(HelloWorldRequest.Builder::build)
.forEach(request::onNext);
request.onCompleted();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.helloworld.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloWorldConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldConsumerApplication.class, args);
}
}

View File

@ -0,0 +1,11 @@
grpc:
client:
hello:
address: localhost:9090
negotiation-type: plaintext
logging:
pattern:
console: "[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5level [%t] [%logger - %line]: %m%n"
level:
com.baeldung.helloworld.consumer: info
include-application-name: false

View File

@ -0,0 +1,89 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-3-grpc</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>helloworld-grpc-java</artifactId>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${io.grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${io.grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<version>${io.grpc.version}</version>
<scope>test</scope>
</dependency>
<!-- we need this because protoc adds a @javax.annotation.Generated annotation to the sources -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${annotation-api.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-maven-plugin.version}</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${io.grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<id>protobuf-compile</id>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
<execution>
<id>protobuf-compile-custom</id>
<goals>
<goal>compile-custom</goal>
<goal>test-compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<io.grpc.version>1.58.0</io.grpc.version>
<protoc.version>3.25.1</protoc.version>
<os-maven-plugin.version>1.7.1</os-maven-plugin.version>
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
<annotation-api.version>1.3.2</annotation-api.version>
</properties>
</project>

View File

@ -0,0 +1,5 @@
/**
* This package contains the gRPC stubs
* generated by the protoc compiler.
*/
package com.baeldung.helloworld.stubs;

View File

@ -0,0 +1,19 @@
syntax = "proto3";
option java_package = "com.baeldung.helloworld.stubs";
option java_multiple_files = true;
message HelloWorldRequest {
// a name to greet, default is "World"
optional string name = 1;
}
message HelloWorldResponse {
string greeting = 1;
}
service HelloWorldService {
rpc SayHello(stream HelloWorldRequest) returns (stream HelloWorldResponse);
}

View File

@ -0,0 +1,35 @@
<?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>
<artifactId>helloworld-grpc-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloworld-grpc-provider</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../../parent-boot-3</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>${grpc-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>helloworld-grpc-java</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
<spring-boot.version>3.2.0</spring-boot.version>
<grpc-spring-boot-starter.version>2.15.0.RELEASE</grpc-spring-boot-starter.version>
</properties>
</project>

View File

@ -0,0 +1,42 @@
package com.baeldung.helloworld.provider;
import com.baeldung.helloworld.stubs.HelloWorldRequest;
import com.baeldung.helloworld.stubs.HelloWorldResponse;
import com.baeldung.helloworld.stubs.HelloWorldServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
@GrpcService
public class HelloWorldController extends HelloWorldServiceGrpc.HelloWorldServiceImplBase {
private static final Logger log = LoggerFactory.getLogger(HelloWorldController.class);
private HelloWorldResponse sayHello(HelloWorldRequest request) {
log.info("Received request: {}", request);
return HelloWorldResponse
.newBuilder()
.setGreeting("Hello "
+ Optional
.of(request.getName())
.map(String::trim)
.filter(s -> !s.isEmpty())
.orElse("World")
+ "!"
)
.build();
}
@Override
public StreamObserver<HelloWorldRequest> sayHello(
StreamObserver<HelloWorldResponse> responseObserver
) {
return StreamObserverUtility.proxyStream(
responseObserver,
this::sayHello
);
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.helloworld.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloWorldProviderApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldProviderApplication.class, args);
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.helloworld.provider;
import io.grpc.stub.StreamObserver;
import java.util.function.Function;
final class StreamObserverUtility {
private StreamObserverUtility() {
}
static <Target, Source> StreamObserver<Source> proxyStream(
StreamObserver<Target> target,
Function<Source, Target> handler
) {
return new StreamObserver<Source>() {
@Override
public void onNext(Source value) {
final Target targetValue = handler.apply(value);
target.onNext(targetValue);
}
@Override
public void onError(Throwable t) {
target.onError(t);
}
@Override
public void onCompleted() {
target.onCompleted();
}
};
}
}

View File

@ -0,0 +1,9 @@
grpc:
server:
port: 9090
logging:
pattern:
console: "[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5level [%t] [%logger - %line]: %m%n"
level:
com.baeldung.helloworld.provider: info
include-application-name: false

View File

@ -0,0 +1,25 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-3-grpc</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>spring-boot-3-grpc</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modules>
<module>helloworld-grpc-java</module>
<module>helloworld-grpc-provider</module>
<module>helloworld-grpc-consumer</module>
</modules>
</project>