diff --git a/docs/src/main/asciidoc/grpc-generation-reference.adoc b/docs/src/main/asciidoc/grpc-generation-reference.adoc index 6d871816c3c33..48c732bcd5123 100644 --- a/docs/src/main/asciidoc/grpc-generation-reference.adoc +++ b/docs/src/main/asciidoc/grpc-generation-reference.adoc @@ -99,6 +99,21 @@ quarkus { } ---- +== Generating Descriptor Set +Protocol Buffers do not contain descriptions of their own types. Thus, given only a raw message without the corresponding .proto file defining its type, it is difficult to extract any useful data. However, the contents of a .proto file can itself be https://protobuf.dev/programming-guides/techniques/#self-description[represented using protocol buffers]. + +By default, Quarkus does not generate these descriptors. Quarkus does provide several configuration options for generating them. These would be added to your `application.properties` or `application.yml` file: + +* `quarkus.generate-code.grpc.descriptor-set.generate` +** Set to `true` to enable generation +* `quarkus.generate-code.grpc.descriptor-set.output-dir` +** Set this to a value relative to the project's build directory (i.e. `target` for Maven, `build` for Gradle) +** Maven default value: `target/generated-sources/grpc` +** Gradle default value: `$buildDir/classes/java/quarkus-generated-sources/grpc` +* `quarkus.generate-code.grpc.descriptor-set.name` +** Name of the descriptor set file to generate +** Default value: `descriptor_set.dsc` + == Configuring gRPC code generation for dependencies You may have dependencies that contain `\*.proto` files you want to compile to Java sources. diff --git a/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java b/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java index 32a0ed9d06172..6c5417239d0a3 100644 --- a/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java +++ b/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/deployment/GrpcCodeGen.java @@ -1,5 +1,6 @@ package io.quarkus.grpc.deployment; +import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; @@ -56,6 +57,9 @@ public class GrpcCodeGen implements CodeGenProvider { private static final String SCAN_FOR_IMPORTS = "quarkus.generate-code.grpc.scan-for-imports"; private static final String POST_PROCESS_SKIP = "quarkus.generate.code.grpc-post-processing.skip"; + private static final String GENERATE_DESCRIPTOR_SET = "quarkus.generate-code.grpc.descriptor-set.generate"; + private static final String DESCRIPTOR_SET_OUTPUT_DIR = "quarkus.generate-code.grpc.descriptor-set.output-dir"; + private static final String DESCRIPTOR_SET_FILENAME = "quarkus.generate-code.grpc.descriptor-set.name"; private Executables executables; private String input; @@ -149,6 +153,11 @@ public boolean trigger(CodeGenContext context) throws CodeGenException { "--q-grpc_out=" + outDir, "--grpc_out=" + outDir, "--java_out=" + outDir)); + + if (shouldGenerateDescriptorSet(context.config())) { + command.add(String.format("--descriptor_set_out=%s", getDescriptorSetOutputFile(context))); + } + command.addAll(protoFiles); ProcessBuilder processBuilder = new ProcessBuilder(command); @@ -262,6 +271,25 @@ private boolean isGeneratingFromAppDependenciesEnabled(Config config) { .filter(value -> !"none".equals(value)).isPresent(); } + private boolean shouldGenerateDescriptorSet(Config config) { + return config.getOptionalValue(GENERATE_DESCRIPTOR_SET, Boolean.class).orElse(FALSE); + } + + private Path getDescriptorSetOutputFile(CodeGenContext context) throws IOException { + var dscOutputDir = context.config().getOptionalValue(DESCRIPTOR_SET_OUTPUT_DIR, String.class) + .map(context.workDir()::resolve) + .orElseGet(context::outDir); + + if (Files.notExists(dscOutputDir)) { + Files.createDirectories(dscOutputDir); + } + + var dscFilename = context.config().getOptionalValue(DESCRIPTOR_SET_FILENAME, String.class) + .orElse("descriptor_set.dsc"); + + return dscOutputDir.resolve(dscFilename).normalize(); + } + private Collection gatherDirectoriesWithImports(Path workDir, CodeGenContext context) throws CodeGenException { Config properties = context.config(); diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/build.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/build.gradle new file mode 100644 index 0000000000000..57535418f2507 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + implementation 'io.quarkus:quarkus-grpc' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +test { + systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/gradle.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/settings.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/settings.gradle new file mode 100644 index 0000000000000..662c07020134c --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} +rootProject.name = 'grpc-descriptor-set-alternate-output-dir' \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/java/org/acme/quarkus/sample/HelloResource.java b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/java/org/acme/quarkus/sample/HelloResource.java new file mode 100644 index 0000000000000..e5c864ff6be0e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/java/org/acme/quarkus/sample/HelloResource.java @@ -0,0 +1,21 @@ +package org.acme.quarkus.sample; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import io.quarkus.example.HelloMsg; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + Integer number = HelloMsg.Status.TEST_ONE.getNumber(); + // return a thing from proto file (for devmode test) + return "hello " + number; + } +} diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/proto/hello.proto b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/proto/hello.proto new file mode 100644 index 0000000000000..4ebcaf36db77a --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/proto/hello.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package io.quarkus.example; + +option java_multiple_files = true; +option java_package = "io.quarkus.example"; + +import "google/protobuf/timestamp.proto"; + + +message HelloMsg { + enum Status { + UNKNOWN = 0; + NOT_SERVING = 1; + TEST_ONE = 2; + } + string message = 1; + google.protobuf.Timestamp date_time = 2; + Status status = 3; +} + +service DevModeService { + rpc Check(HelloMsg) returns (HelloMsg); +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties new file mode 100644 index 0000000000000..f4576b12d2123 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties @@ -0,0 +1,3 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true +quarkus.generate-code.grpc.descriptor-set.name=hello.dsc +quarkus.generate-code.grpc.descriptor-set.output-dir=proto \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/build.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/build.gradle new file mode 100644 index 0000000000000..57535418f2507 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + implementation 'io.quarkus:quarkus-grpc' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +test { + systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/gradle.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/settings.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/settings.gradle new file mode 100644 index 0000000000000..687590ad96980 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} +rootProject.name = 'grpc-descriptor-set-alternate-output' \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/java/org/acme/quarkus/sample/HelloResource.java b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/java/org/acme/quarkus/sample/HelloResource.java new file mode 100644 index 0000000000000..e5c864ff6be0e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/java/org/acme/quarkus/sample/HelloResource.java @@ -0,0 +1,21 @@ +package org.acme.quarkus.sample; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import io.quarkus.example.HelloMsg; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + Integer number = HelloMsg.Status.TEST_ONE.getNumber(); + // return a thing from proto file (for devmode test) + return "hello " + number; + } +} diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/proto/hello.proto b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/proto/hello.proto new file mode 100644 index 0000000000000..4ebcaf36db77a --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/proto/hello.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package io.quarkus.example; + +option java_multiple_files = true; +option java_package = "io.quarkus.example"; + +import "google/protobuf/timestamp.proto"; + + +message HelloMsg { + enum Status { + UNKNOWN = 0; + NOT_SERVING = 1; + TEST_ONE = 2; + } + string message = 1; + google.protobuf.Timestamp date_time = 2; + Status status = 3; +} + +service DevModeService { + rpc Check(HelloMsg) returns (HelloMsg); +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/resources/application.properties new file mode 100644 index 0000000000000..8181681cb4951 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set-alternate-output/src/main/resources/application.properties @@ -0,0 +1,2 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true +quarkus.generate-code.grpc.descriptor-set.name=hello.dsc \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/build.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/build.gradle new file mode 100644 index 0000000000000..57535418f2507 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + implementation 'io.quarkus:quarkus-grpc' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +test { + systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/gradle.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/settings.gradle b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/settings.gradle new file mode 100644 index 0000000000000..46dc110045b06 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} +rootProject.name = 'grpc-descriptor-set' \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/java/org/acme/quarkus/sample/HelloResource.java b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/java/org/acme/quarkus/sample/HelloResource.java new file mode 100644 index 0000000000000..e5c864ff6be0e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/java/org/acme/quarkus/sample/HelloResource.java @@ -0,0 +1,21 @@ +package org.acme.quarkus.sample; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import io.quarkus.example.HelloMsg; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + Integer number = HelloMsg.Status.TEST_ONE.getNumber(); + // return a thing from proto file (for devmode test) + return "hello " + number; + } +} diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/proto/hello.proto b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/proto/hello.proto new file mode 100644 index 0000000000000..4ebcaf36db77a --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/proto/hello.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package io.quarkus.example; + +option java_multiple_files = true; +option java_package = "io.quarkus.example"; + +import "google/protobuf/timestamp.proto"; + + +message HelloMsg { + enum Status { + UNKNOWN = 0; + NOT_SERVING = 1; + TEST_ONE = 2; + } + string message = 1; + google.protobuf.Timestamp date_time = 2; + Status status = 3; +} + +service DevModeService { + rpc Check(HelloMsg) returns (HelloMsg); +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/resources/application.properties new file mode 100644 index 0000000000000..b39cd85e72737 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/grpc-descriptor-set/src/main/resources/application.properties @@ -0,0 +1 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true \ No newline at end of file diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputBuildTest.java new file mode 100644 index 0000000000000..e108c207370d7 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputBuildTest.java @@ -0,0 +1,27 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class GrpcDescriptorSetAlternateOutputBuildTest extends QuarkusGradleWrapperTestBase { + + @Test + public void testGrpcDescriptorSetAlternateOutput() throws Exception { + var projectDir = getProjectDir("grpc-descriptor-set-alternate-output"); + var buildResult = runGradleWrapper(projectDir, "clean", "build"); + assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusGenerateCode"))).isTrue(); + + var expectedOutputDir = projectDir.toPath() + .resolve("build") + .resolve("classes") + .resolve("java") + .resolve("quarkus-generated-sources") + .resolve("grpc"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("hello.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputDirBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputDirBuildTest.java new file mode 100644 index 0000000000000..579042e321d11 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetAlternateOutputDirBuildTest.java @@ -0,0 +1,24 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class GrpcDescriptorSetAlternateOutputDirBuildTest extends QuarkusGradleWrapperTestBase { + + @Test + public void testGrpcDescriptorSetAlternateOutputDir() throws Exception { + var projectDir = getProjectDir("grpc-descriptor-set-alternate-output-dir"); + var buildResult = runGradleWrapper(projectDir, "clean", "build"); + assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusGenerateCode"))).isTrue(); + + var expectedOutputDir = projectDir.toPath() + .resolve("build") + .resolve("proto"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("hello.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetBuildTest.java new file mode 100644 index 0000000000000..c5506309e0bc8 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/GrpcDescriptorSetBuildTest.java @@ -0,0 +1,27 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class GrpcDescriptorSetBuildTest extends QuarkusGradleWrapperTestBase { + + @Test + public void testGrpcDescriptorSet() throws Exception { + var projectDir = getProjectDir("grpc-descriptor-set"); + var buildResult = runGradleWrapper(projectDir, "clean", "build"); + assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusGenerateCode"))).isTrue(); + + var expectedOutputDir = projectDir.toPath() + .resolve("build") + .resolve("classes") + .resolve("java") + .resolve("quarkus-generated-sources") + .resolve("grpc"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("descriptor_set.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/pom.xml b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/pom.xml new file mode 100644 index 0000000000000..8f819511f53e6 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + quarkus-integration-test-grpc-descriptor-sets-parent + io.quarkus + 999-SNAPSHOT + + + quarkus-integration-test-grpc-descriptor-sets-alternate-output-dir + Quarkus - Integration Tests - gRPC - Descriptor Sets - Alternate Output Dir + + + + + maven-surefire-plugin + + + ${project.build.directory} + + + + + + diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java new file mode 100644 index 0000000000000..4922f5e81e09e --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java @@ -0,0 +1,41 @@ +package io.quarkus.grpc.examples.hello; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + +import examples.GreeterGrpc; +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcClient; +import io.smallrye.mutiny.Uni; + +@Path("/hello") +public class HelloWorldEndpoint { + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @GrpcClient("hello") + MutinyGreeterGrpc.MutinyGreeterStub mutinyHelloService; + + @GET + @Path("/blocking/{name}") + public String helloBlocking(@PathParam("name") String name) { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()); + return generateResponse(reply); + + } + + @GET + @Path("/mutiny/{name}") + public Uni helloMutiny(@PathParam("name") String name) { + return mutinyHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()) + .onItem().transform((reply) -> generateResponse(reply)); + } + + public String generateResponse(HelloReply reply) { + return String.format("%s! HelloWorldService has been called %d number of times.", reply.getMessage(), reply.getCount()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java new file mode 100644 index 0000000000000..6b13fdf54462d --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java @@ -0,0 +1,23 @@ +package io.quarkus.grpc.examples.hello; + +import java.util.concurrent.atomic.AtomicInteger; + +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcService; +import io.smallrye.mutiny.Uni; + +@GrpcService +public class HelloWorldService extends MutinyGreeterGrpc.GreeterImplBase { + + AtomicInteger counter = new AtomicInteger(); + + @Override + public Uni sayHello(HelloRequest request) { + int count = counter.incrementAndGet(); + String name = request.getName(); + return Uni.createFrom().item("Hello " + name) + .map(res -> HelloReply.newBuilder().setMessage(res).setCount(count).build()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/proto/helloworld.proto b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/proto/helloworld.proto new file mode 100644 index 0000000000000..c50ba71b3b4fa --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/proto/helloworld.proto @@ -0,0 +1,21 @@ +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "examples"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + required string name = 1; +} + +message HelloReply { + required string message = 1; + optional int32 count = 2; +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties new file mode 100644 index 0000000000000..214afae1821d5 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/main/resources/application.properties @@ -0,0 +1,12 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true +quarkus.generate-code.grpc.descriptor-set.name=hello.dsc +quarkus.generate-code.grpc.descriptor-set.output-dir=proto + +quarkus.grpc.server.port=9001 + +quarkus.grpc.clients.hello.host=localhost +quarkus.grpc.clients.hello.port=9001 + +%vertx.quarkus.grpc.clients.hello.port=8081 +%vertx.quarkus.grpc.clients.hello.use-quarkus-grpc-client=true +%vertx.quarkus.grpc.server.use-separate-server=false diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java new file mode 100644 index 0000000000000..a982554fb6d75 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output-dir/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java @@ -0,0 +1,21 @@ +package io.quarkus.grpc.examples.hello; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class DescriptorSetExistsTest { + + @Test + public void descriptorSetExists() { + var expectedOutputDir = Path.of(System.getProperty("build.dir")) + .resolve("proto"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("hello.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/pom.xml b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/pom.xml new file mode 100644 index 0000000000000..91203496badde --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + quarkus-integration-test-grpc-descriptor-sets-parent + io.quarkus + 999-SNAPSHOT + + + quarkus-integration-test-grpc-descriptor-sets-alternate-output + Quarkus - Integration Tests - gRPC - Descriptor Sets - Alternate Output + + + + + maven-surefire-plugin + + + ${project.build.directory} + + + + + + diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java new file mode 100644 index 0000000000000..4922f5e81e09e --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java @@ -0,0 +1,41 @@ +package io.quarkus.grpc.examples.hello; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + +import examples.GreeterGrpc; +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcClient; +import io.smallrye.mutiny.Uni; + +@Path("/hello") +public class HelloWorldEndpoint { + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @GrpcClient("hello") + MutinyGreeterGrpc.MutinyGreeterStub mutinyHelloService; + + @GET + @Path("/blocking/{name}") + public String helloBlocking(@PathParam("name") String name) { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()); + return generateResponse(reply); + + } + + @GET + @Path("/mutiny/{name}") + public Uni helloMutiny(@PathParam("name") String name) { + return mutinyHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()) + .onItem().transform((reply) -> generateResponse(reply)); + } + + public String generateResponse(HelloReply reply) { + return String.format("%s! HelloWorldService has been called %d number of times.", reply.getMessage(), reply.getCount()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java new file mode 100644 index 0000000000000..6b13fdf54462d --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java @@ -0,0 +1,23 @@ +package io.quarkus.grpc.examples.hello; + +import java.util.concurrent.atomic.AtomicInteger; + +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcService; +import io.smallrye.mutiny.Uni; + +@GrpcService +public class HelloWorldService extends MutinyGreeterGrpc.GreeterImplBase { + + AtomicInteger counter = new AtomicInteger(); + + @Override + public Uni sayHello(HelloRequest request) { + int count = counter.incrementAndGet(); + String name = request.getName(); + return Uni.createFrom().item("Hello " + name) + .map(res -> HelloReply.newBuilder().setMessage(res).setCount(count).build()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/proto/helloworld.proto b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/proto/helloworld.proto new file mode 100644 index 0000000000000..c50ba71b3b4fa --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/proto/helloworld.proto @@ -0,0 +1,21 @@ +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "examples"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + required string name = 1; +} + +message HelloReply { + required string message = 1; + optional int32 count = 2; +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/resources/application.properties b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/resources/application.properties new file mode 100644 index 0000000000000..20a1d5d62db45 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/main/resources/application.properties @@ -0,0 +1,11 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true +quarkus.generate-code.grpc.descriptor-set.name=hello.dsc + +quarkus.grpc.server.port=9001 + +quarkus.grpc.clients.hello.host=localhost +quarkus.grpc.clients.hello.port=9001 + +%vertx.quarkus.grpc.clients.hello.port=8081 +%vertx.quarkus.grpc.clients.hello.use-quarkus-grpc-client=true +%vertx.quarkus.grpc.server.use-separate-server=false diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java new file mode 100644 index 0000000000000..0c1a586f0ec38 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set-alternate-output/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java @@ -0,0 +1,22 @@ +package io.quarkus.grpc.examples.hello; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class DescriptorSetExistsTest { + + @Test + public void descriptorSetExists() { + var expectedOutputDir = Path.of(System.getProperty("build.dir")) + .resolve("generated-sources") + .resolve("grpc"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("hello.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/pom.xml b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/pom.xml new file mode 100644 index 0000000000000..cc417c76e19b9 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + quarkus-integration-test-grpc-descriptor-sets-parent + io.quarkus + 999-SNAPSHOT + + + quarkus-integration-test-grpc-descriptor-sets-descriptor-set + Quarkus - Integration Tests - gRPC - Descriptor Sets - Descriptor Set + + + + + maven-surefire-plugin + + + ${project.build.directory} + + + + + + diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java new file mode 100644 index 0000000000000..4922f5e81e09e --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldEndpoint.java @@ -0,0 +1,41 @@ +package io.quarkus.grpc.examples.hello; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + +import examples.GreeterGrpc; +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcClient; +import io.smallrye.mutiny.Uni; + +@Path("/hello") +public class HelloWorldEndpoint { + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @GrpcClient("hello") + MutinyGreeterGrpc.MutinyGreeterStub mutinyHelloService; + + @GET + @Path("/blocking/{name}") + public String helloBlocking(@PathParam("name") String name) { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()); + return generateResponse(reply); + + } + + @GET + @Path("/mutiny/{name}") + public Uni helloMutiny(@PathParam("name") String name) { + return mutinyHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()) + .onItem().transform((reply) -> generateResponse(reply)); + } + + public String generateResponse(HelloReply reply) { + return String.format("%s! HelloWorldService has been called %d number of times.", reply.getMessage(), reply.getCount()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java new file mode 100644 index 0000000000000..6b13fdf54462d --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/java/io/quarkus/grpc/examples/hello/HelloWorldService.java @@ -0,0 +1,23 @@ +package io.quarkus.grpc.examples.hello; + +import java.util.concurrent.atomic.AtomicInteger; + +import examples.HelloReply; +import examples.HelloRequest; +import examples.MutinyGreeterGrpc; +import io.quarkus.grpc.GrpcService; +import io.smallrye.mutiny.Uni; + +@GrpcService +public class HelloWorldService extends MutinyGreeterGrpc.GreeterImplBase { + + AtomicInteger counter = new AtomicInteger(); + + @Override + public Uni sayHello(HelloRequest request) { + int count = counter.incrementAndGet(); + String name = request.getName(); + return Uni.createFrom().item("Hello " + name) + .map(res -> HelloReply.newBuilder().setMessage(res).setCount(count).build()); + } +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/proto/helloworld.proto b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/proto/helloworld.proto new file mode 100644 index 0000000000000..c50ba71b3b4fa --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/proto/helloworld.proto @@ -0,0 +1,21 @@ +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "examples"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + required string name = 1; +} + +message HelloReply { + required string message = 1; + optional int32 count = 2; +} diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/resources/application.properties b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/resources/application.properties new file mode 100644 index 0000000000000..b63c49d1fd261 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/main/resources/application.properties @@ -0,0 +1,10 @@ +quarkus.generate-code.grpc.descriptor-set.generate=true + +quarkus.grpc.server.port=9001 + +quarkus.grpc.clients.hello.host=localhost +quarkus.grpc.clients.hello.port=9001 + +%vertx.quarkus.grpc.clients.hello.port=8081 +%vertx.quarkus.grpc.clients.hello.use-quarkus-grpc-client=true +%vertx.quarkus.grpc.server.use-separate-server=false diff --git a/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java new file mode 100644 index 0000000000000..4b64f9caccae6 --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/grpc-descriptor-set/src/test/java/io/quarkus/grpc/examples/hello/DescriptorSetExistsTest.java @@ -0,0 +1,22 @@ +package io.quarkus.grpc.examples.hello; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class DescriptorSetExistsTest { + + @Test + public void descriptorSetExists() { + var expectedOutputDir = Path.of(System.getProperty("build.dir")) + .resolve("generated-sources") + .resolve("grpc"); + + assertThat(expectedOutputDir).exists(); + assertThat(expectedOutputDir.resolve("descriptor_set.dsc")) + .exists() + .isNotEmptyFile(); + } +} diff --git a/integration-tests/grpc-descriptor-sets/pom.xml b/integration-tests/grpc-descriptor-sets/pom.xml new file mode 100644 index 0000000000000..45a21572d641d --- /dev/null +++ b/integration-tests/grpc-descriptor-sets/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + + quarkus-integration-tests-parent + io.quarkus + 999-SNAPSHOT + + + quarkus-integration-test-grpc-descriptor-sets-parent + Quarkus - Integration Tests - gRPC - Descriptor Sets - Parent + pom + + + grpc-descriptor-set + grpc-descriptor-set-alternate-output + grpc-descriptor-set-alternate-output-dir + + + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-grpc + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.awaitility + awaitility + test + + + org.assertj + assertj-core + test + + + io.quarkus + quarkus-test-grpc + ${project.version} + test + + + + + io.quarkus + quarkus-grpc-deployment + ${project.version} + pom + test + + + * + * + + + + + io.quarkus + quarkus-resteasy-reactive-deployment + ${project.version} + pom + test + + + * + * + + + + + + + + + io.quarkus + quarkus-maven-plugin + + + + generate-code + build + + + + + + + + diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index b623b32388ee6..ce18414ff5768 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -373,6 +373,7 @@ locales redis-devservices + grpc-descriptor-sets grpc-inprocess grpc-vertx grpc-tls