From bc8cb24bfb13f79143df7c95df15e213791dbeda Mon Sep 17 00:00:00 2001 From: Santiago Pericas-Geertsen Date: Tue, 13 Aug 2024 11:42:33 -0400 Subject: [PATCH] New MP gRPC end-to-end example that uses gRPC proxy-based API (#65) New MP gRPC end-to-end example that uses new gRPC proxy-based API. Signed-off-by: Santiago Pericas-Geertsen --- examples/microprofile/grpc/README.md | 15 ++ examples/microprofile/grpc/pom.xml | 114 +++++++++++++++ .../microprofile/grpc/StringService.java | 88 ++++++++++++ .../grpc/StringServiceClient.java | 68 +++++++++ .../microprofile/grpc/package-info.java | 16 +++ .../grpc/src/main/proto/strings.proto | 30 ++++ .../src/main/resources/META-INF/beans.xml | 25 ++++ .../grpc/src/main/resources/application.yaml | 48 +++++++ .../grpc/src/main/resources/client.p12 | Bin 0 -> 4181 bytes .../src/main/resources/logging.properties | 29 ++++ .../grpc/src/main/resources/server.p12 | Bin 0 -> 4133 bytes .../microprofile/grpc/StringServiceTest.java | 130 ++++++++++++++++++ examples/microprofile/pom.xml | 1 + 13 files changed, 564 insertions(+) create mode 100644 examples/microprofile/grpc/README.md create mode 100644 examples/microprofile/grpc/pom.xml create mode 100644 examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringService.java create mode 100644 examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringServiceClient.java create mode 100644 examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/package-info.java create mode 100644 examples/microprofile/grpc/src/main/proto/strings.proto create mode 100644 examples/microprofile/grpc/src/main/resources/META-INF/beans.xml create mode 100644 examples/microprofile/grpc/src/main/resources/application.yaml create mode 100644 examples/microprofile/grpc/src/main/resources/client.p12 create mode 100644 examples/microprofile/grpc/src/main/resources/logging.properties create mode 100644 examples/microprofile/grpc/src/main/resources/server.p12 create mode 100644 examples/microprofile/grpc/src/test/java/io/helidon/examples/microprofile/grpc/StringServiceTest.java diff --git a/examples/microprofile/grpc/README.md b/examples/microprofile/grpc/README.md new file mode 100644 index 000000000..4fa6c5906 --- /dev/null +++ b/examples/microprofile/grpc/README.md @@ -0,0 +1,15 @@ +# Helidon gRPC MP Example + +This examples shows a simple application written using Helidon gRPC MP API: + +- StringService: a gRPC service implementation that uses MP +- StringServiceClient: an interface from which a client proxy can be created to call StringService remote methods +- StringServiceTest: a sample test that starts a server and tests the client and server components +- application.yaml: configuration for server and client channels + +## Build and run + +```shell +mvn package +java -jar target/helidon-examples-microprofile-grpc.jar +``` \ No newline at end of file diff --git a/examples/microprofile/grpc/pom.xml b/examples/microprofile/grpc/pom.xml new file mode 100644 index 000000000..fcd36e798 --- /dev/null +++ b/examples/microprofile/grpc/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.1.0-SNAPSHOT + + + io.helidon.examples.microprofile + helidon-examples-microprofile-grpc + Helidon Examples Microprofile gRPC + + + Microprofile example that uses gRPC + + + + + io.helidon.grpc + helidon-grpc-core + + + io.helidon.microprofile.grpc + helidon-microprofile-grpc-core + + + io.helidon.microprofile.grpc + helidon-microprofile-grpc-server + + + io.helidon.microprofile.grpc + helidon-microprofile-grpc-client + + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + + + io.helidon.webserver.testing.junit5 + helidon-webserver-testing-junit5-grpc + test + + + io.helidon.logging + helidon-logging-jul + runtime + + + + javax.annotation + javax.annotation-api + provided + true + + + + + + + + kr.motd.maven + os-maven-plugin + ${version.plugin.os} + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + + + + compile + test-compile + + + + + + + \ No newline at end of file diff --git a/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringService.java b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringService.java new file mode 100644 index 000000000..046793bd5 --- /dev/null +++ b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringService.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.examples.microprofile.grpc; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import io.helidon.grpc.api.Grpc; +import io.helidon.grpc.core.CollectingObserver; + +import io.grpc.stub.StreamObserver; +import jakarta.enterprise.context.ApplicationScoped; + +/** + * An implementation of a string service. + */ +@Grpc.GrpcService +@ApplicationScoped +public class StringService { + + /** + * Uppercase a string. + * + * @param request string message + * @return string message + */ + @Grpc.Unary("Upper") + public Strings.StringMessage upper(Strings.StringMessage request) { + return newMessage(request.getText().toUpperCase()); + } + + /** + * Lowercase a string. + * + * @param request string message + * @return string message + */ + @Grpc.Unary("Lower") + public Strings.StringMessage lower(Strings.StringMessage request) { + return newMessage(request.getText().toLowerCase()); + } + + /** + * Split a string using space delimiters. + * + * @param request string message + * @return stream of string messages + */ + @Grpc.ServerStreaming("Split") + public Stream split(Strings.StringMessage request) { + String[] parts = request.getText().split(" "); + return Stream.of(parts).map(this::newMessage); + } + + /** + * Join a stream of messages using spaces. + * + * @param observer stream of messages + * @return single message as a stream + */ + @Grpc.ClientStreaming("Join") + public StreamObserver join(StreamObserver observer) { + return CollectingObserver.create( + Collectors.joining(" "), + observer, + Strings.StringMessage::getText, + this::newMessage); + } + + private Strings.StringMessage newMessage(String text) { + return Strings.StringMessage.newBuilder().setText(text).build(); + } +} + diff --git a/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringServiceClient.java b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringServiceClient.java new file mode 100644 index 000000000..b03ee3e90 --- /dev/null +++ b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/StringServiceClient.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.examples.microprofile.grpc; + +import java.util.stream.Stream; + +import io.helidon.grpc.api.Grpc; + +import io.grpc.stub.StreamObserver; + +/** + * A client for a {@link StringService}. + */ +@Grpc.GrpcService("StringService") +@Grpc.GrpcChannel("string-channel") // see application.yaml +public interface StringServiceClient { + + /** + * Uppercase a string. + * + * @param request string message + * @return string message + */ + @Grpc.Unary("Upper") + Strings.StringMessage upper(Strings.StringMessage request); + + /** + * Lowercase a string. + * + * @param request string message + * @return string message + */ + @Grpc.Unary("Lower") + Strings.StringMessage lower(Strings.StringMessage request); + + /** + * Split a string using space delimiters. + * + * @param request string message + * @return stream of string messages + */ + @Grpc.ServerStreaming("Split") + Stream split(Strings.StringMessage request); + + /** + * Join a stream of messages using spaces. + * + * @param observer stream of messages + * @return single message as a stream + */ + @Grpc.ClientStreaming("Join") + StreamObserver join(StreamObserver observer); +} + diff --git a/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/package-info.java b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/package-info.java new file mode 100644 index 000000000..fbf691b80 --- /dev/null +++ b/examples/microprofile/grpc/src/main/java/io/helidon/examples/microprofile/grpc/package-info.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.helidon.examples.microprofile.grpc; diff --git a/examples/microprofile/grpc/src/main/proto/strings.proto b/examples/microprofile/grpc/src/main/proto/strings.proto new file mode 100644 index 000000000..48c8bd30d --- /dev/null +++ b/examples/microprofile/grpc/src/main/proto/strings.proto @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +syntax = "proto3"; +option java_package = "io.helidon.examples.microprofile.grpc"; + +service StringService { + rpc Upper (StringMessage) returns (StringMessage) {} + rpc Lower (StringMessage) returns (StringMessage) {} + rpc Split (StringMessage) returns (stream StringMessage) {} + rpc Join (stream StringMessage) returns (StringMessage) {} +} + +message StringMessage { + string text = 1; +} diff --git a/examples/microprofile/grpc/src/main/resources/META-INF/beans.xml b/examples/microprofile/grpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..69f490f1a --- /dev/null +++ b/examples/microprofile/grpc/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + diff --git a/examples/microprofile/grpc/src/main/resources/application.yaml b/examples/microprofile/grpc/src/main/resources/application.yaml new file mode 100644 index 000000000..fdc488cfd --- /dev/null +++ b/examples/microprofile/grpc/src/main/resources/application.yaml @@ -0,0 +1,48 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +server: + port: 0 + tls: + trust: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "server.p12" + private-key: + keystore: + passphrase: "password" + resource: + resource-path: "server.p12" + +grpc: + client: + channels: + - name: "string-channel" + port: 0 + tls: + trust: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "client.p12" + private-key: + keystore: + passphrase: "password" + resource: + resource-path: "client.p12" \ No newline at end of file diff --git a/examples/microprofile/grpc/src/main/resources/client.p12 b/examples/microprofile/grpc/src/main/resources/client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4eb3b8325cd0190163032aca86e1d4fc94856822 GIT binary patch literal 4181 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 U@+;F6i_J(6+nRj}N+2@-U-0Veh5!Hn literal 0 HcmV?d00001 diff --git a/examples/microprofile/grpc/src/test/java/io/helidon/examples/microprofile/grpc/StringServiceTest.java b/examples/microprofile/grpc/src/test/java/io/helidon/examples/microprofile/grpc/StringServiceTest.java new file mode 100644 index 000000000..b6e9410f1 --- /dev/null +++ b/examples/microprofile/grpc/src/test/java/io/helidon/examples/microprofile/grpc/StringServiceTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.helidon.examples.microprofile.grpc; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import io.helidon.grpc.api.Grpc; +import io.helidon.microprofile.grpc.client.GrpcConfigurablePort; +import io.helidon.microprofile.testing.junit5.HelidonTest; + +import io.grpc.stub.StreamObserver; +import jakarta.inject.Inject; +import jakarta.ws.rs.client.WebTarget; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasSize; + +@HelidonTest +class StringServiceTest { + + @Inject + private WebTarget webTarget; + + @Inject + @Grpc.GrpcProxy + private StringServiceClient client; + + @BeforeEach + void updatePort() { + if (client instanceof GrpcConfigurablePort c) { + c.channelPort(webTarget.getUri().getPort()); + } + } + + @Test + void testUnaryUpper() { + Strings.StringMessage res = client.upper(newMessage("hello")); + assertThat(res.getText(), is("HELLO")); + } + + @Test + void testUnaryLower() { + Strings.StringMessage res = client.lower(newMessage("HELLO")); + assertThat(res.getText(), is("hello")); + } + + @Test + void testServerStreamingSplit() { + Stream stream = client.split(newMessage("hello world")); + List value = stream.toList(); + assertThat(value, hasSize(2)); + assertThat(value, contains(newMessage("hello"), newMessage("world"))); + } + + @Test + void testClientStreamingJoin() throws InterruptedException { + ListObserver response = new ListObserver<>(); + StreamObserver request = client.join(response); + request.onNext(newMessage("hello")); + request.onNext(newMessage("world")); + request.onCompleted(); + List value = response.value(); + assertThat(value.getFirst(), is(newMessage("hello world"))); + } + + /** + * Helper method to create a string message from a string. + * + * @param data the string + * @return the string message + */ + Strings.StringMessage newMessage(String data) { + return Strings.StringMessage.newBuilder().setText(data).build(); + } + + /** + * Helper class to collect a list of observed values. + * + * @param the type of values + */ + static class ListObserver implements StreamObserver { + private static final long TIMEOUT_SECONDS = 10; + + private List value = new ArrayList<>(); + private final CountDownLatch latch = new CountDownLatch(1); + + public List value() throws InterruptedException { + boolean b = latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS); + assert b; + return value; + } + + @Override + public void onNext(T value) { + this.value.add(value); + } + + @Override + public void onError(Throwable t) { + value = null; + } + + @Override + public void onCompleted() { + latch.countDown(); + } + } +} + diff --git a/examples/microprofile/pom.xml b/examples/microprofile/pom.xml index db26994f3..fd4c017e8 100644 --- a/examples/microprofile/pom.xml +++ b/examples/microprofile/pom.xml @@ -52,6 +52,7 @@ http-status-count-mp lra telemetry + grpc threads