You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2020/09/16 07:17:35 UTC
[camel-quarkus] branch master updated: gRPC native support
This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/master by this push:
new 776e28d gRPC native support
776e28d is described below
commit 776e28d0736f981f7587f384cd550546dd13096e
Author: James Netherton <ja...@gmail.com>
AuthorDate: Tue Sep 15 19:19:45 2020 +0100
gRPC native support
Fixes #762
---
.../ROOT/pages/reference/components/grpc.adoc | 4 +-
.../ROOT/pages/reference/extensions/grpc.adoc | 16 +-
docs/modules/ROOT/pages/reference/index.adoc | 4 +-
.../component/grpc/deployment/GrpcProcessor.java | 46 ----
extensions-jvm/pom.xml | 1 -
.../grpc/deployment/pom.xml | 4 +
.../component/grpc/deployment/GrpcProcessor.java | 243 +++++++++++++++++++++
{extensions-jvm => extensions}/grpc/pom.xml | 1 -
.../grpc/runtime/pom.xml | 14 ++
.../grpc/runtime/src/main/doc/configuration.adoc | 6 +
.../quarkus/grpc/runtime/CamelGrpcRecorder.java | 85 +++++++
.../grpc/runtime/CamelQuarkusBindableService.java | 27 +++
.../runtime/QuarkusBindableServiceFactory.java | 63 ++++++
.../grpc/runtime/graal/GrpcSubstitutions.java | 36 +++
.../main/resources/META-INF/quarkus-extension.yaml | 3 +-
extensions/pom.xml | 1 +
.../grpc}/pom.xml | 75 +++++--
.../quarkus/component/grpc/it/GrpcResource.java | 0
.../camel/quarkus/component/grpc/it/GrpcRoute.java | 2 +-
.../quarkus/component/grpc/it/PingPongImpl.java | 2 +-
.../grpc}/src/main/proto/pingpong.proto | 0
.../camel/quarkus/component/grpc/it/GrpcIT.java | 23 ++
.../component/grpc/it/GrpcServerTestResource.java | 4 +-
.../camel/quarkus/component/grpc/it/GrpcTest.java | 7 +-
integration-tests/pom.xml | 1 +
tooling/scripts/test-categories.yaml | 1 +
26 files changed, 587 insertions(+), 82 deletions(-)
diff --git a/docs/modules/ROOT/pages/reference/components/grpc.adoc b/docs/modules/ROOT/pages/reference/components/grpc.adoc
index 864d462..3848442 100644
--- a/docs/modules/ROOT/pages/reference/components/grpc.adoc
+++ b/docs/modules/ROOT/pages/reference/components/grpc.adoc
@@ -4,8 +4,8 @@
= gRPC
:cq-artifact-id: camel-quarkus-grpc
:cq-artifact-id-base: grpc
-:cq-native-supported: false
-:cq-status: Preview
+:cq-native-supported: true
+:cq-status: Stable
:cq-deprecated: false
:cq-jvm-since: 1.0.0
:cq-native-since: 1.0.0
diff --git a/docs/modules/ROOT/pages/reference/extensions/grpc.adoc b/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
index d7308b8..3099af1 100644
--- a/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
@@ -4,15 +4,15 @@
= gRPC
:page-aliases: extensions/grpc.adoc
:cq-artifact-id: camel-quarkus-grpc
-:cq-native-supported: false
-:cq-status: Preview
+:cq-native-supported: true
+:cq-status: Stable
:cq-description: Expose gRPC endpoints and access external gRPC endpoints.
:cq-deprecated: false
:cq-jvm-since: 1.0.0
:cq-native-since: 1.0.0
[.badges]
-[.badge-key]##JVM since##[.badge-supported]##1.0.0## [.badge-key]##Native##[.badge-unsupported]##unsupported##
+[.badge-key]##JVM since##[.badge-supported]##1.0.0## [.badge-key]##Native since##[.badge-supported]##1.0.0##
Expose gRPC endpoints and access external gRPC endpoints.
@@ -33,3 +33,13 @@ Please refer to the above link for usage and configuration details.
----
Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
+
+== Additional Camel Quarkus configuration
+
+This extension leverages https://quarkus.io/guides/grpc-service-implementation[Quarkus gRPC]. The configuration of the gRPC consumer is different than normal,
+since Quarkus manages the lifecycle of the gRPC server. This means that the consumer endpoint host and port is driven by the configuration properties `quarkus.grpc.server.host`
+and `quarkus.grpc.server.port` and thus the Camel gRPC endpoint configuration for the host & port is effectively ignored. But, it's still good practice to have the
+endpoint configuration host / port mirror the Quarkus gRPC host / port property values to avoid confusion and ambiguity.
+
+The full list of Quarkus gRPC configuration options can be found at the https://quarkus.io/guides/grpc-service-implementation#server-configuration[Quarkus gRPC guide].
+
diff --git a/docs/modules/ROOT/pages/reference/index.adoc b/docs/modules/ROOT/pages/reference/index.adoc
index 9fbb486..d80cd13 100644
--- a/docs/modules/ROOT/pages/reference/index.adoc
+++ b/docs/modules/ROOT/pages/reference/index.adoc
@@ -389,8 +389,8 @@ Stable | 1.0.0 | Unmarshal unstructured data to objects using Logstash based Gro
| xref:reference/extensions/groovy.adoc[Groovy] | camel-quarkus-groovy | [.camel-element-JVM]##JVM## +
Preview | 1.0.0 | Evaluate a Groovy script.
-| xref:reference/extensions/grpc.adoc[gRPC] | camel-quarkus-grpc | [.camel-element-JVM]##JVM## +
-Preview | 1.0.0 | Expose gRPC endpoints and access external gRPC endpoints.
+| xref:reference/extensions/grpc.adoc[gRPC] | camel-quarkus-grpc | [.camel-element-Native]##Native## +
+Stable | 1.0.0 | Expose gRPC endpoints and access external gRPC endpoints.
| xref:reference/extensions/guava-eventbus.adoc[Guava EventBus] | camel-quarkus-guava-eventbus | [.camel-element-JVM]##JVM## +
Preview | 1.1.0 | Send and receive messages to/from Guava EventBus.
diff --git a/extensions-jvm/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java b/extensions-jvm/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java
deleted file mode 100644
index 0e1b125..0000000
--- a/extensions-jvm/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.grpc.deployment;
-
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.annotations.ExecutionTime;
-import io.quarkus.deployment.annotations.Record;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.pkg.steps.NativeBuild;
-import org.apache.camel.quarkus.core.JvmOnlyRecorder;
-import org.jboss.logging.Logger;
-
-class GrpcProcessor {
-
- private static final Logger LOG = Logger.getLogger(GrpcProcessor.class);
- private static final String FEATURE = "camel-grpc";
-
- @BuildStep
- FeatureBuildItem feature() {
- return new FeatureBuildItem(FEATURE);
- }
-
- /**
- * Remove this once this extension starts supporting the native mode.
- */
- @BuildStep(onlyIf = NativeBuild.class)
- @Record(value = ExecutionTime.RUNTIME_INIT)
- void warnJvmInNative(JvmOnlyRecorder recorder) {
- JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time
- recorder.warnJvmInNative(FEATURE); // warn at runtime
- }
-}
diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml
index 9eb2fcc..f31e5a1 100644
--- a/extensions-jvm/pom.xml
+++ b/extensions-jvm/pom.xml
@@ -78,7 +78,6 @@
<module>google-bigquery</module>
<module>google-pubsub</module>
<module>groovy</module>
- <module>grpc</module>
<module>guava-eventbus</module>
<module>hazelcast</module>
<module>hdfs</module>
diff --git a/extensions-jvm/grpc/deployment/pom.xml b/extensions/grpc/deployment/pom.xml
similarity index 94%
rename from extensions-jvm/grpc/deployment/pom.xml
rename to extensions/grpc/deployment/pom.xml
index 71010eb..8b16ee2 100644
--- a/extensions-jvm/grpc/deployment/pom.xml
+++ b/extensions/grpc/deployment/pom.xml
@@ -31,6 +31,10 @@
<dependencies>
<dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-grpc-deployment</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core-deployment</artifactId>
</dependency>
diff --git a/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java b/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java
new file mode 100644
index 0000000..9ea7dda
--- /dev/null
+++ b/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/GrpcProcessor.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.grpc.deployment;
+
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import io.grpc.BindableService;
+import io.grpc.stub.AbstractAsyncStub;
+import io.grpc.stub.AbstractBlockingStub;
+import io.grpc.stub.AbstractFutureStub;
+import io.grpc.stub.StreamObserver;
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.GeneratedBeanBuildItem;
+import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.gizmo.ClassCreator;
+import io.quarkus.gizmo.FieldCreator;
+import io.quarkus.gizmo.MethodCreator;
+import io.quarkus.gizmo.MethodDescriptor;
+import io.quarkus.gizmo.ResultHandle;
+import io.quarkus.grpc.deployment.BindableServiceBuildItem;
+import org.apache.camel.component.grpc.GrpcComponent;
+import org.apache.camel.component.grpc.server.GrpcMethodHandler;
+import org.apache.camel.quarkus.core.deployment.spi.CamelBeanBuildItem;
+import org.apache.camel.quarkus.grpc.runtime.CamelGrpcRecorder;
+import org.apache.camel.quarkus.grpc.runtime.CamelQuarkusBindableService;
+import org.apache.camel.quarkus.grpc.runtime.QuarkusBindableServiceFactory;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.IndexView;
+import org.jboss.jandex.MethodInfo;
+import org.jboss.jandex.Type;
+
+class GrpcProcessor {
+
+ private static final DotName BINDABLE_SERVICE_DOT_NAME = DotName.createSimple(BindableService.class.getName());
+ private static final DotName[] STUB_CLASS_DOT_NAMES = new DotName[] {
+ DotName.createSimple(AbstractAsyncStub.class.getName()),
+ DotName.createSimple(AbstractBlockingStub.class.getName()),
+ DotName.createSimple(AbstractFutureStub.class.getName())
+ };
+ private static final String FEATURE = "camel-grpc";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+
+ @BuildStep
+ void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ CombinedIndexBuildItem combinedIndexBuildItem) {
+
+ IndexView index = combinedIndexBuildItem.getIndex();
+ for (DotName dotName : STUB_CLASS_DOT_NAMES) {
+ index.getAllKnownSubclasses(dotName)
+ .stream()
+ .map(classInfo -> new ReflectiveClassBuildItem(true, false, classInfo.name().toString()))
+ .forEach(reflectiveClass::produce);
+ }
+ }
+
+ @BuildStep
+ void createBindableServiceBeans(
+ BuildProducer<GeneratedBeanBuildItem> generatedBean,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+ BuildProducer<BindableServiceBuildItem> bindableService,
+ CombinedIndexBuildItem combinedIndexBuildItem) {
+
+ Set<String> services = generateBindableServiceBeans(generatedBean, reflectiveClass, combinedIndexBuildItem.getIndex());
+ services.stream()
+ .map(DotName::createSimple)
+ .map(BindableServiceBuildItem::new)
+ .forEach(bindableService::produce);
+ }
+
+ @BuildStep
+ void quarkusBindableServiceFactoryBean(BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
+ additionalBeans.produce(AdditionalBeanBuildItem.unremovableOf(QuarkusBindableServiceFactory.class));
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ CamelBeanBuildItem createGrpcComponent(CamelGrpcRecorder recorder) {
+ return new CamelBeanBuildItem(
+ "grpc",
+ GrpcComponent.class.getName(),
+ recorder.createGrpcComponent());
+ }
+
+ private Set<String> generateBindableServiceBeans(BuildProducer<GeneratedBeanBuildItem> generatedBean,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClass, IndexView index) {
+ Set<String> generatedBindableServiceClassNames = new HashSet<>();
+ Collection<ClassInfo> bindableServiceImpls = index.getAllKnownImplementors(BINDABLE_SERVICE_DOT_NAME);
+
+ // Generate implementation classes from any abstract gRPC BindableService implementations included in the application archive
+ // Override the various sync and async methods so that requests can be intercepted and delegated to Camel routing
+ // This mimics similar logic in DefaultBindableServiceFactory that uses Javassist ProxyFactory & MethodHandler
+ for (ClassInfo service : bindableServiceImpls) {
+ if (!Modifier.isAbstract(service.flags())) {
+ continue;
+ }
+
+ String superClassName = service.name().toString();
+ String generatedClassName = superClassName + "QuarkusMethodHandler";
+ generatedBindableServiceClassNames.add(generatedClassName);
+
+ // Register the service classes for reflection
+ reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, service.name().toString()));
+ reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, service.enclosingClass().toString()));
+ reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, generatedClassName));
+
+ try (ClassCreator classCreator = ClassCreator.builder()
+ .classOutput(new GeneratedBeanGizmoAdaptor(generatedBean))
+ .className(generatedClassName)
+ .superClass(superClassName)
+ .interfaces(CamelQuarkusBindableService.class)
+ .build()) {
+
+ classCreator.addAnnotation(Singleton.class);
+
+ FieldCreator serverMethodHandler = classCreator
+ .getFieldCreator("methodHandler", GrpcMethodHandler.class.getName())
+ .setModifiers(Modifier.PRIVATE);
+
+ // Create constructor
+ try (MethodCreator initMethod = classCreator.getMethodCreator("<init>", void.class)) {
+ initMethod.setModifiers(Modifier.PUBLIC);
+ initMethod.invokeSpecialMethod(MethodDescriptor.ofMethod(superClassName, "<init>", void.class),
+ initMethod.getThis());
+ initMethod.returnValue(null);
+ }
+
+ // Create setMethodHandler override
+ try (MethodCreator setMethodHandlerMethod = classCreator.getMethodCreator("setMethodHandler", void.class,
+ GrpcMethodHandler.class)) {
+ setMethodHandlerMethod.setModifiers(Modifier.PUBLIC);
+
+ ResultHandle self = setMethodHandlerMethod.getThis();
+ ResultHandle methodHandlerInstance = setMethodHandlerMethod.getMethodParam(0);
+
+ setMethodHandlerMethod.writeInstanceField(serverMethodHandler.getFieldDescriptor(), self,
+ methodHandlerInstance);
+ setMethodHandlerMethod.returnValue(null);
+ }
+
+ // Override service methods that the gRPC component is interested in
+ // E.g methods with one or two parameters where one is of type StreamObserver
+ List<MethodInfo> methods = service.methods();
+ for (MethodInfo method : methods) {
+ if (isCandidateServiceMethod(method)) {
+ String[] params = method.parameters()
+ .stream()
+ .map(type -> type.name().toString())
+ .toArray(String[]::new);
+
+ ClassInfo classInfo = index
+ .getClassByName(DotName.createSimple(GrpcMethodHandler.class.getName()));
+
+ String returnType = method.returnType().name().toString();
+ try (MethodCreator methodCreator = classCreator.getMethodCreator(method.name(), returnType, params)) {
+ method.exceptions()
+ .stream()
+ .map(type -> type.name().toString())
+ .forEach(methodCreator::addException);
+
+ if (method.parameters().size() == 1) {
+ ResultHandle returnValue = generateGrpcDelegateMethod(classInfo, serverMethodHandler,
+ methodCreator,
+ method, "handleForConsumerStrategy");
+ methodCreator.returnValue(returnValue);
+ } else if (method.parameters().size() == 2) {
+ generateGrpcDelegateMethod(classInfo, serverMethodHandler, methodCreator, method,
+ "handle");
+ methodCreator.returnValue(null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return generatedBindableServiceClassNames;
+ }
+
+ private boolean isCandidateServiceMethod(MethodInfo method) {
+ List<Type> parameters = method.parameters();
+ if (parameters.size() == 1) {
+ return parameters.get(0).name().toString().equals(StreamObserver.class.getName());
+ } else if (parameters.size() == 2) {
+ return parameters.get(1).name().toString().equals(StreamObserver.class.getName());
+ }
+ return false;
+ }
+
+ private ResultHandle generateGrpcDelegateMethod(ClassInfo classInfo, FieldCreator fieldCreator, MethodCreator methodCreator,
+ MethodInfo sourceMethod, String targetMethod) {
+
+ MethodInfo method = classInfo.methods()
+ .stream()
+ .filter(methodInfo -> methodInfo.name().equals(targetMethod))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException(
+ "Unable to find target method " + targetMethod + " on GrpcServerMethodHandler"));
+
+ ResultHandle methodNameParam = methodCreator.load(sourceMethod.name());
+ ResultHandle[] methodParams;
+ if (sourceMethod.parameters().size() == 1) {
+ methodParams = new ResultHandle[] { methodCreator.getMethodParam(0), methodNameParam };
+ } else {
+ methodParams = new ResultHandle[] { methodCreator.getMethodParam(0), methodCreator.getMethodParam(1),
+ methodNameParam };
+ }
+
+ ResultHandle resultHandle = methodCreator.readInstanceField(fieldCreator.getFieldDescriptor(), methodCreator.getThis());
+ return methodCreator.invokeVirtualMethod(method, resultHandle, methodParams);
+ }
+}
diff --git a/extensions-jvm/grpc/pom.xml b/extensions/grpc/pom.xml
similarity index 97%
rename from extensions-jvm/grpc/pom.xml
rename to extensions/grpc/pom.xml
index c220608..e49d35a 100644
--- a/extensions-jvm/grpc/pom.xml
+++ b/extensions/grpc/pom.xml
@@ -33,6 +33,5 @@
<modules>
<module>deployment</module>
<module>runtime</module>
- <module>integration-test</module>
</modules>
</project>
diff --git a/extensions-jvm/grpc/runtime/pom.xml b/extensions/grpc/runtime/pom.xml
similarity index 87%
rename from extensions-jvm/grpc/runtime/pom.xml
rename to extensions/grpc/runtime/pom.xml
index 4c7f6cd..454767a 100644
--- a/extensions-jvm/grpc/runtime/pom.xml
+++ b/extensions/grpc/runtime/pom.xml
@@ -48,12 +48,26 @@
<dependencies>
<dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-grpc</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-grpc</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-tcnative-boringssl-static</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.graalvm.nativeimage</groupId>
+ <artifactId>svm</artifactId>
</dependency>
</dependencies>
diff --git a/extensions/grpc/runtime/src/main/doc/configuration.adoc b/extensions/grpc/runtime/src/main/doc/configuration.adoc
new file mode 100644
index 0000000..f903be5
--- /dev/null
+++ b/extensions/grpc/runtime/src/main/doc/configuration.adoc
@@ -0,0 +1,6 @@
+This extension leverages https://quarkus.io/guides/grpc-service-implementation[Quarkus gRPC]. The configuration of the gRPC consumer is different than normal,
+since Quarkus manages the lifecycle of the gRPC server. This means that the consumer endpoint host and port is driven by the configuration properties `quarkus.grpc.server.host`
+and `quarkus.grpc.server.port` and thus the Camel gRPC endpoint configuration for the host & port is effectively ignored. But, it's still good practice to have the
+endpoint configuration host / port mirror the Quarkus gRPC host / port property values to avoid confusion and ambiguity.
+
+The full list of Quarkus gRPC configuration options can be found at the https://quarkus.io/guides/grpc-service-implementation#server-configuration[Quarkus gRPC guide].
diff --git a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelGrpcRecorder.java b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelGrpcRecorder.java
new file mode 100644
index 0000000..ba13200
--- /dev/null
+++ b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelGrpcRecorder.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.grpc.runtime;
+
+import java.util.Map;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.component.grpc.GrpcComponent;
+import org.apache.camel.component.grpc.GrpcConfiguration;
+import org.apache.camel.component.grpc.GrpcConsumer;
+import org.apache.camel.component.grpc.GrpcEndpoint;
+import org.apache.camel.component.grpc.server.BindableServiceFactory;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.service.ServiceHelper;
+
+import static org.apache.camel.component.grpc.GrpcConstants.GRPC_BINDABLE_SERVICE_FACTORY_NAME;
+
+@Recorder
+public class CamelGrpcRecorder {
+
+ public RuntimeValue<GrpcComponent> createGrpcComponent() {
+ return new RuntimeValue<>(new QuarkusGrpcComponent());
+ }
+
+ @Component("grpc")
+ static final class QuarkusGrpcComponent extends GrpcComponent {
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+ GrpcConfiguration config = new GrpcConfiguration();
+ config = parseConfiguration(config, uri);
+
+ Endpoint endpoint = new QuarkusGrpcEndpoint(uri, this, config);
+ setProperties(endpoint, parameters);
+ return endpoint;
+ }
+ }
+
+ static final class QuarkusGrpcEndpoint extends GrpcEndpoint {
+
+ public QuarkusGrpcEndpoint(String uri, GrpcComponent component, GrpcConfiguration config) throws Exception {
+ super(uri, component, config);
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ return new QuarkusGrpcConsumer(this, processor, configuration);
+ }
+ }
+
+ static final class QuarkusGrpcConsumer extends GrpcConsumer {
+
+ public QuarkusGrpcConsumer(GrpcEndpoint endpoint, Processor processor, GrpcConfiguration configuration) {
+ super(endpoint, processor, configuration);
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ // Quarkus gRPC extension handles server startup so we only need to configure the BindableService for this consumer endpoint
+ ServiceHelper.startService(getProcessor());
+ BindableServiceFactory bindableServiceFactory = CamelContextHelper.lookup(endpoint.getCamelContext(),
+ GRPC_BINDABLE_SERVICE_FACTORY_NAME, BindableServiceFactory.class);
+ bindableServiceFactory.createBindableService(this);
+ }
+ }
+}
diff --git a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelQuarkusBindableService.java b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelQuarkusBindableService.java
new file mode 100644
index 0000000..4a4426b
--- /dev/null
+++ b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/CamelQuarkusBindableService.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.grpc.runtime;
+
+import io.grpc.BindableService;
+import org.apache.camel.component.grpc.server.GrpcMethodHandler;
+
+/**
+ * A Camel Quarkus specific BindableService that enables a GrpcMethodHandler to be configured
+ */
+public interface CamelQuarkusBindableService extends BindableService {
+ void setMethodHandler(GrpcMethodHandler methodHandler);
+}
diff --git a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/QuarkusBindableServiceFactory.java b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/QuarkusBindableServiceFactory.java
new file mode 100644
index 0000000..7ffd3fd
--- /dev/null
+++ b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/QuarkusBindableServiceFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.grpc.runtime;
+
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import io.grpc.BindableService;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.grpc.GrpcConsumer;
+import org.apache.camel.component.grpc.GrpcEndpoint;
+import org.apache.camel.component.grpc.GrpcUtils;
+import org.apache.camel.component.grpc.server.BindableServiceFactory;
+import org.apache.camel.component.grpc.server.GrpcMethodHandler;
+
+import static org.apache.camel.component.grpc.GrpcConstants.GRPC_BINDABLE_SERVICE_FACTORY_NAME;
+
+/**
+ * A custom BindableServiceFactory which finds, configures and returns the appropriate BindableService
+ * that was dynamically generated at build time
+ */
+@Singleton
+@Named(GRPC_BINDABLE_SERVICE_FACTORY_NAME)
+public class QuarkusBindableServiceFactory implements BindableServiceFactory {
+
+ @Inject
+ Instance<CamelQuarkusBindableService> bindableServices;
+
+ @Override
+ public BindableService createBindableService(GrpcConsumer consumer) {
+ GrpcEndpoint endpoint = (GrpcEndpoint) consumer.getEndpoint();
+ CamelContext camelContext = endpoint.getCamelContext();
+
+ Class<?> baseClass = GrpcUtils.constructGrpcImplBaseClass(endpoint.getServicePackage(), endpoint.getServiceName(),
+ camelContext);
+
+ // Find the BindableService implementation that was generated in GrpcProcessor and configure the GrpcMethodHandler
+ CamelQuarkusBindableService bindableService = bindableServices.stream()
+ .filter(service -> baseClass.isAssignableFrom(service.getClass()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException(
+ "Unable to find generated class for service " + endpoint.getServiceName()));
+
+ bindableService.setMethodHandler(new GrpcMethodHandler(consumer));
+ return bindableService;
+ }
+}
diff --git a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/graal/GrpcSubstitutions.java b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/graal/GrpcSubstitutions.java
new file mode 100644
index 0000000..9ca3e9f
--- /dev/null
+++ b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/graal/GrpcSubstitutions.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.grpc.runtime.graal;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.apache.camel.component.grpc.GrpcConsumer;
+import org.apache.camel.component.grpc.server.BindableServiceFactory;
+
+final class GrpcSubstitutions {
+}
+
+@TargetClass(GrpcConsumer.class)
+final class SubstituteGrpcConsumer {
+
+ @Substitute
+ private BindableServiceFactory getBindableServiceFactory() {
+ // Remove unwanted references to javassist.
+ // This is effectively replaced by the BindableServiceFactory lookup in QuarkusGrpcConsumer.doStart()
+ return null;
+ }
+}
diff --git a/extensions-jvm/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
similarity index 97%
rename from extensions-jvm/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
rename to extensions/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 4a016fd..3e14a06 100644
--- a/extensions-jvm/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/extensions/grpc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -24,9 +24,8 @@
name: "Camel gRPC"
description: "Expose gRPC endpoints and access external gRPC endpoints"
metadata:
- unlisted: true
guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/grpc.html"
categories:
- "integration"
status:
- - "preview"
+ - "stable"
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 129356f..2540be7 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -109,6 +109,7 @@
<module>google-sheets</module>
<module>graphql</module>
<module>grok</module>
+ <module>grpc</module>
<module>gson</module>
<module>http</module>
<module>hystrix</module>
diff --git a/extensions-jvm/grpc/integration-test/pom.xml b/integration-tests/grpc/pom.xml
similarity index 73%
rename from extensions-jvm/grpc/integration-test/pom.xml
rename to integration-tests/grpc/pom.xml
index d1711ee..43e931c 100644
--- a/extensions-jvm/grpc/integration-test/pom.xml
+++ b/integration-tests/grpc/pom.xml
@@ -21,25 +21,14 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.camel.quarkus</groupId>
- <artifactId>camel-quarkus-build-parent-it</artifactId>
+ <artifactId>camel-quarkus-integration-tests</artifactId>
<version>1.2.0-SNAPSHOT</version>
- <relativePath>../../../poms/build-parent-it/pom.xml</relativePath>
</parent>
- <artifactId>camel-quarkus-grpc-integration-test</artifactId>
- <name>Camel Quarkus :: gRPC :: Integration Test</name>
+ <artifactId>camel-quarkus-integration-test-grpc</artifactId>
+ <name>Camel Quarkus :: Integration Tests :: gRPC</name>
<description>Integration tests for Camel Quarkus gRPC extension</description>
- <properties>
- <!-- mvnd, a.k.a. Maven Daemon: https://github.com/mvndaemon/mvnd -->
- <!-- The following rule tells mvnd to build the listed deployment modules before this module. -->
- <!-- This is important because mvnd builds modules in parallel by default. The deployment modules are not -->
- <!-- explicit dependencies of this module in the Maven sense, although they are required by the Quarkus Maven plugin. -->
- <!-- Please update the rule whenever you change the dependencies of this module by running -->
- <!-- mvn process-resources -Pformat from the root directory -->
- <mvnd.builder.rule>camel-quarkus-grpc-deployment</mvnd.builder.rule>
- </properties>
-
<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
@@ -70,6 +59,34 @@
<artifactId>camel-quarkus-integration-test-support</artifactId>
<scope>test</scope>
</dependency>
+
+ <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-direct-deployment</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-grpc-deployment</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
<build>
@@ -155,4 +172,34 @@
</plugin>
</plugins>
</build>
+
+ <profiles>
+ <profile>
+ <id>native</id>
+ <activation>
+ <property>
+ <name>native</name>
+ </property>
+ </activation>
+ <properties>
+ <quarkus.package.type>native</quarkus.package.type>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcResource.java b/integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcResource.java
similarity index 100%
rename from extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcResource.java
rename to integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcResource.java
diff --git a/extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java b/integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java
similarity index 92%
rename from extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java
rename to integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java
index fab0cb3..4adfd56 100644
--- a/extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java
+++ b/integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/GrpcRoute.java
@@ -25,7 +25,7 @@ public class GrpcRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
- from("grpc://localhost:{{camel.grpc.consumer.port}}/org.apache.camel.quarkus.component.grpc.it.model.PingPong?synchronous=true")
+ from("grpc://localhost:9000/org.apache.camel.quarkus.component.grpc.it.model.PingPong?synchronous=true")
.process(exchange -> {
final Message message = exchange.getMessage();
final PingRequest request = message.getBody(PingRequest.class);
diff --git a/extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java b/integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java
similarity index 100%
rename from extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java
rename to integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java
index db153ca..6f7b74d 100644
--- a/extensions-jvm/grpc/integration-test/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java
+++ b/integration-tests/grpc/src/main/java/org/apache/camel/quarkus/component/grpc/it/PingPongImpl.java
@@ -31,8 +31,8 @@ public class PingPongImpl extends org.apache.camel.quarkus.component.grpc.it.mod
request.getPingName());
PongResponse response = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE)
.setPongId(request.getPingId()).build();
+
responseObserver.onNext(response);
responseObserver.onCompleted();
}
-
}
diff --git a/extensions-jvm/grpc/integration-test/src/main/proto/pingpong.proto b/integration-tests/grpc/src/main/proto/pingpong.proto
similarity index 100%
rename from extensions-jvm/grpc/integration-test/src/main/proto/pingpong.proto
rename to integration-tests/grpc/src/main/proto/pingpong.proto
diff --git a/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcIT.java b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcIT.java
new file mode 100644
index 0000000..c06814c
--- /dev/null
+++ b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcIT.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.grpc.it;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+class GrpcIT extends GrpcTest {
+}
diff --git a/extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java
similarity index 90%
rename from extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java
rename to integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java
index c647fd2..b355d54 100644
--- a/extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java
+++ b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java
@@ -36,9 +36,7 @@ public class GrpcServerTestResource implements QuarkusTestResourceLifecycleManag
try {
final int port = AvailablePortFinder.getNextAvailable();
grpcServer = ServerBuilder.forPort(port).addService(new PingPongImpl()).build().start();
- return CollectionHelper.mapOf(
- "camel.grpc.test.server.port", String.valueOf(port),
- "camel.grpc.consumer.port", String.valueOf(AvailablePortFinder.getNextAvailable()));
+ return CollectionHelper.mapOf("camel.grpc.test.server.port", String.valueOf(port));
} catch (Exception e) {
throw new RuntimeException("Could not start gRPC server", e);
}
diff --git a/extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java
similarity index 93%
rename from extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java
rename to integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java
index ab5b708..4625a0c 100644
--- a/extensions-jvm/grpc/integration-test/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java
+++ b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcTest.java
@@ -25,7 +25,6 @@ import org.apache.camel.quarkus.component.grpc.it.model.PingPongGrpc;
import org.apache.camel.quarkus.component.grpc.it.model.PingPongGrpc.PingPongBlockingStub;
import org.apache.camel.quarkus.component.grpc.it.model.PingRequest;
import org.apache.camel.quarkus.component.grpc.it.model.PongResponse;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -35,14 +34,11 @@ import static org.hamcrest.Matchers.equalTo;
@QuarkusTestResource(GrpcServerTestResource.class)
class GrpcTest {
- @ConfigProperty(name = "camel.grpc.consumer.port")
- int consumerPort;
-
@Test
public void consumer() {
ManagedChannel syncRequestChannel = null;
try {
- syncRequestChannel = ManagedChannelBuilder.forAddress("localhost", consumerPort).usePlaintext().build();
+ syncRequestChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();
final PingPongBlockingStub blockingStub = PingPongGrpc.newBlockingStub(syncRequestChannel);
final PingRequest pingRequest = PingRequest.newBuilder()
@@ -73,5 +69,4 @@ class GrpcTest {
.body(equalTo("PINGPONG"));
}
-
}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 7d7d48c..722472e 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -95,6 +95,7 @@
<module>google</module>
<module>graphql</module>
<module>grok</module>
+ <module>grpc</module>
<module>http</module>
<module>hystrix</module>
<module>infinispan</module>
diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml
index 986f35a..cbcef00 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -25,6 +25,7 @@ cloud:
- azure
- consul
- elasticsearch-rest
+ - grpc
- smallrye-reactive-messaging
core-main-validation:
- core