This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch 3.15.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 066b9de2f4910512fb294ef240cbbdc4f1a4cabc
Author: James Netherton <[email protected]>
AuthorDate: Thu Nov 14 10:10:21 2024 +0000

    Exclude unwanted gRPC services from build time discovery
    
    Fixes #6780
---
 .../ROOT/pages/reference/extensions/grpc.adoc      | 15 ++++++
 .../CamelGrpcServiceExcludesBuildItem.java         | 54 ++++++++++++++++++++++
 .../component/grpc/deployment/GrpcProcessor.java   | 24 ++++++++--
 .../quarkus/grpc/runtime/GrpcBuildTimeConfig.java  | 19 ++++++++
 .../resources/org/acme/proto/f/proto-f-1.proto     | 35 ++++++++++++++
 .../acme/proto/f/sub/package/other/proto-f-4.proto | 35 ++++++++++++++
 .../org/acme/proto/f/sub/package/proto-f-3.proto   | 35 ++++++++++++++
 .../resources/org/acme/proto/f/sub/proto-f-2.proto | 35 ++++++++++++++
 .../quarkus/component/grpc/it/GrpcResource.java    | 19 ++++++++
 .../grpc/src/main/resources/application.properties |  5 +-
 .../camel/quarkus/component/grpc/it/GrpcTest.java  | 16 +++++++
 11 files changed, 287 insertions(+), 5 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/grpc.adoc 
b/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
index b51897b24b..ed035b1fd1 100644
--- a/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/grpc.adoc
@@ -160,6 +160,21 @@ At present there is no support for integrating Camel 
Quarkus gRPC with Quarkus g
 | Configuration property | Type | Default
 
 
+|icon:lock[title=Fixed at build time] 
[[quarkus.camel.grpc.service-excludes]]`link:#quarkus.camel.grpc.service-excludes[quarkus.camel.grpc.service-excludes]`
+
+Excludes classes from the build time scanning of gRPC service classes.
+This can be useful if there are gRPC services that you want to exclude from 
participating in Camel gRPC route
+operations. The value is a comma separated list of class name patterns.
+You can specify the fully qualified class name of individual classes or use 
path patterns to match multiple classes.
+For example to exclude all classes starting with `MyService` use: 
`++**++MyService++*++`.
+To exclude all services from a specific package use: `com.services.++*++`.
+To exclude all services from a specific package and its sub-packages, use
+double wildcards: `com.services.++**++`.
+And to exclude all services from two specific packages use:
+`com.services.++*++,com.other.services.++*++`.
+| List of `string`
+| 
+
 |icon:lock[title=Fixed at build time] 
[[quarkus.camel.grpc.codegen.enabled]]`link:#quarkus.camel.grpc.codegen.enabled[quarkus.camel.grpc.codegen.enabled]`
 
 If `true`, Camel Quarkus gRPC code generation is run for .proto files 
discovered from the `proto` directory, or from dependencies specified in the 
`scan-for-proto` or `scan-for-imports` options. When `false`, code generation 
for .proto files is disabled.
diff --git 
a/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/CamelGrpcServiceExcludesBuildItem.java
 
b/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/CamelGrpcServiceExcludesBuildItem.java
new file mode 100644
index 0000000000..295299b289
--- /dev/null
+++ 
b/extensions/grpc/deployment/src/main/java/org/apache/camel/quarkus/component/grpc/deployment/CamelGrpcServiceExcludesBuildItem.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util.HashSet;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import io.quarkus.builder.item.SimpleBuildItem;
+import org.apache.camel.util.AntPathMatcher;
+import org.jboss.jandex.ClassInfo;
+
+final class CamelGrpcServiceExcludesBuildItem extends SimpleBuildItem {
+    private static final Set<String> DEFAULT_SERVICE_EXCLUDES = Set.of(
+            // Exclude unwanted gRPC services shaded into 
org.apache.kafka:kafka-clients
+            "org.apache.kafka.shaded.**");
+
+    private final Set<String> serviceExcludes = new HashSet<>();
+
+    CamelGrpcServiceExcludesBuildItem(Set<String> excludes) {
+        this.serviceExcludes.addAll(DEFAULT_SERVICE_EXCLUDES);
+        if (!excludes.isEmpty()) {
+            this.serviceExcludes.addAll(excludes);
+        }
+    }
+
+    Set<String> getServiceExcludes() {
+        return serviceExcludes;
+    }
+
+    Predicate<ClassInfo> serviceExcludesFilter() {
+        return classInfo -> getServiceExcludes()
+                .stream()
+                .noneMatch(exclude -> {
+                    String className = 
classInfo.name().toString().replace(".", "/");
+                    String excludePattern = exclude.replace(".", "/");
+                    return AntPathMatcher.INSTANCE.match(excludePattern, 
className);
+                });
+    }
+}
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
index 0c6b9b0c72..0361b6b793 100644
--- 
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
@@ -18,8 +18,10 @@ package org.apache.camel.quarkus.component.grpc.deployment;
 
 import java.lang.reflect.Modifier;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 import com.google.api.client.json.GenericJson;
 import io.grpc.BindableService;
@@ -44,6 +46,7 @@ import io.quarkus.gizmo.ResultHandle;
 import jakarta.enterprise.context.Dependent;
 import org.apache.camel.component.grpc.server.GrpcMethodHandler;
 import org.apache.camel.quarkus.grpc.runtime.CamelQuarkusBindableService;
+import org.apache.camel.quarkus.grpc.runtime.GrpcBuildTimeConfig;
 import org.apache.camel.quarkus.grpc.runtime.QuarkusBindableServiceFactory;
 import org.jboss.jandex.ClassInfo;
 import org.jboss.jandex.DotName;
@@ -69,13 +72,22 @@ class GrpcProcessor {
     }
 
     @BuildStep
-    void registerForReflection(BuildProducer<ReflectiveClassBuildItem> 
reflectiveClass,
-            CombinedIndexBuildItem combinedIndexBuildItem) {
+    CamelGrpcServiceExcludesBuildItem 
camelGrpcServiceExcludes(GrpcBuildTimeConfig config) {
+        return new 
CamelGrpcServiceExcludesBuildItem(config.serviceExcludes.orElse(Collections.emptySet()));
+    }
+
+    @BuildStep
+    void registerForReflection(
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+            CombinedIndexBuildItem combinedIndexBuildItem,
+            CamelGrpcServiceExcludesBuildItem camelGrpcServiceExcludes) {
 
         IndexView index = combinedIndexBuildItem.getIndex();
         for (DotName dotName : STUB_CLASS_DOT_NAMES) {
             index.getAllKnownSubclasses(dotName)
                     .stream()
+                    .filter(camelGrpcServiceExcludes.serviceExcludesFilter())
+                    .peek(classInfo -> logDebugMessage("Discovered gRPC stub 
class %s", classInfo.name().toString()))
                     .map(classInfo -> 
ReflectiveClassBuildItem.builder(classInfo.name().toString()).methods()
                             .build())
                     .forEach(reflectiveClass::produce);
@@ -94,10 +106,14 @@ class GrpcProcessor {
     void createBindableServiceBeans(
             BuildProducer<GeneratedBeanBuildItem> generatedBean,
             BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
-            CombinedIndexBuildItem combinedIndexBuildItem) {
+            CombinedIndexBuildItem combinedIndexBuildItem,
+            CamelGrpcServiceExcludesBuildItem camelGrpcServiceExcludes) {
 
         IndexView index = combinedIndexBuildItem.getIndex();
-        Collection<ClassInfo> bindableServiceImpls = 
index.getAllKnownImplementors(BINDABLE_SERVICE_DOT_NAME);
+        Collection<ClassInfo> bindableServiceImpls = 
index.getAllKnownImplementors(BINDABLE_SERVICE_DOT_NAME)
+                .stream()
+                .filter(camelGrpcServiceExcludes.serviceExcludesFilter())
+                .collect(Collectors.toSet());
 
         // 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
diff --git 
a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/GrpcBuildTimeConfig.java
 
b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/GrpcBuildTimeConfig.java
index 0f7a3eda56..0b2275d527 100644
--- 
a/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/GrpcBuildTimeConfig.java
+++ 
b/extensions/grpc/runtime/src/main/java/org/apache/camel/quarkus/grpc/runtime/GrpcBuildTimeConfig.java
@@ -18,6 +18,8 @@ package org.apache.camel.quarkus.grpc.runtime;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 
 import io.quarkus.runtime.annotations.ConfigGroup;
 import io.quarkus.runtime.annotations.ConfigItem;
@@ -26,6 +28,23 @@ import io.quarkus.runtime.annotations.ConfigRoot;
 
 @ConfigRoot(name = "camel.grpc", phase = ConfigPhase.BUILD_TIME)
 public class GrpcBuildTimeConfig {
+    /**
+     * Excludes classes from the build time scanning of gRPC service classes.
+     * This can be useful if there are gRPC services that you want to exclude 
from participating in Camel gRPC route
+     * operations. The value is a comma separated list of class name patterns.
+     * You can specify the fully qualified class name of individual classes or 
use path patterns to match multiple classes.
+     * For example to exclude all classes starting with `MyService` use: 
`++**++MyService++*++`.
+     * To exclude all services from a specific package use: 
`com.services.++*++`.
+     * To exclude all services from a specific package and its sub-packages, 
use
+     * double wildcards: `com.services.++**++`.
+     * And to exclude all services from two specific packages use:
+     * `com.services.++*++,com.other.services.++*++`.
+     *
+     * @asciidoclet
+     */
+    @ConfigItem
+    public Optional<Set<String>> serviceExcludes;
+
     /**
      * Build time configuration options for Camel Quarkus gRPC code generator.
      */
diff --git 
a/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/proto-f-1.proto
 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/proto-f-1.proto
new file mode 100644
index 0000000000..015711872d
--- /dev/null
+++ 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/proto-f-1.proto
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "org.acme.proto.f";
+option java_outer_classname = "PingPongProtoF";
+
+package org.acme.proto.f;
+
+service TestF {
+  rpc PingSyncSync (PingRequestF) returns (PongResponseF) {}
+}
+
+message PingRequestF {
+  string ping_name = 1;
+}
+
+message PongResponseF {
+  string pong_name = 1;
+}
\ No newline at end of file
diff --git 
a/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/other/proto-f-4.proto
 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/other/proto-f-4.proto
new file mode 100644
index 0000000000..c1d70c6ce5
--- /dev/null
+++ 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/other/proto-f-4.proto
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "org.acme.proto.f.sub.dir.other";
+option java_outer_classname = "PingPongProtoF";
+
+package org.acme.proto.sub.dir.other.f;
+
+service TestF {
+  rpc PingSyncSync (PingRequestF) returns (PongResponseF) {}
+}
+
+message PingRequestF {
+  string ping_name = 1;
+}
+
+message PongResponseF {
+  string pong_name = 1;
+}
\ No newline at end of file
diff --git 
a/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/proto-f-3.proto
 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/proto-f-3.proto
new file mode 100644
index 0000000000..930ffefd6e
--- /dev/null
+++ 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/package/proto-f-3.proto
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "org.acme.proto.f.sub.dir";
+option java_outer_classname = "PingPongProtoF";
+
+package org.acme.proto.sub.dir.f;
+
+service TestF {
+  rpc PingSyncSync (PingRequestF) returns (PongResponseF) {}
+}
+
+message PingRequestF {
+  string ping_name = 1;
+}
+
+message PongResponseF {
+  string pong_name = 1;
+}
\ No newline at end of file
diff --git 
a/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/proto-f-2.proto
 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/proto-f-2.proto
new file mode 100644
index 0000000000..1597a70cb2
--- /dev/null
+++ 
b/integration-tests-support/grpc/src/main/resources/org/acme/proto/f/sub/proto-f-2.proto
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "org.acme.proto.f.sub";
+option java_outer_classname = "PingPongProtoF";
+
+package org.acme.proto.f.sub;
+
+service TestF {
+  rpc PingSyncSync (PingRequestF) returns (PongResponseF) {}
+}
+
+message PingRequestF {
+  string ping_name = 1;
+}
+
+message PongResponseF {
+  string pong_name = 1;
+}
\ No newline at end of file
diff --git 
a/integration-tests/grpc/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
index d9aa432a61..b680c8d0bb 100644
--- 
a/integration-tests/grpc/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
@@ -19,7 +19,11 @@ package org.apache.camel.quarkus.component.grpc.it;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.InstanceHandle;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import jakarta.ws.rs.GET;
@@ -34,6 +38,7 @@ import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.quarkus.component.grpc.it.model.PingRequest;
 import org.apache.camel.quarkus.component.grpc.it.model.PongResponse;
+import org.apache.camel.quarkus.grpc.runtime.CamelQuarkusBindableService;
 
 import static 
org.apache.camel.component.grpc.GrpcConstants.GRPC_METHOD_NAME_HEADER;
 
@@ -184,4 +189,18 @@ public class GrpcResource {
                 PongResponse.class);
         return response.getPongName();
     }
+
+    @Path("/services")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<String> services() {
+        return Arc.container()
+                .listAll(CamelQuarkusBindableService.class)
+                .stream()
+                .map(InstanceHandle::get)
+                .map(Object::getClass)
+                .map(Class::getSuperclass)
+                .map(Class::getName)
+                .collect(Collectors.toSet());
+    }
 }
diff --git a/integration-tests/grpc/src/main/resources/application.properties 
b/integration-tests/grpc/src/main/resources/application.properties
index ec91806a1e..7c3e77db04 100644
--- a/integration-tests/grpc/src/main/resources/application.properties
+++ b/integration-tests/grpc/src/main/resources/application.properties
@@ -22,5 +22,8 @@ 
quarkus.camel.grpc.codegen.scan-for-imports=com.google.protobuf:protobuf-java,or
 
 # Test codegen scanning for proto files in other dependencies
 
quarkus.camel.grpc.codegen.scan-for-proto=org.apache.camel.quarkus:camel-quarkus-integration-tests-support-grpc
-quarkus.camel.grpc.codegen.scan-for-proto-includes."org.apache.camel.quarkus\:camel-quarkus-integration-tests-support-grpc"=org/acme/proto/a/*,org/acme/proto/b/proto-b.proto,org/acme/proto/c/**,org/acme/proto/d/**,org/acme/proto/e/**
+quarkus.camel.grpc.codegen.scan-for-proto-includes."org.apache.camel.quarkus\:camel-quarkus-integration-tests-support-grpc"=org/acme/proto/a/*,org/acme/proto/b/proto-b.proto,org/acme/proto/c/**,org/acme/proto/d/**,org/acme/proto/e/**,org/acme/proto/f/**
 
quarkus.camel.grpc.codegen.scan-for-proto-excludes."org.apache.camel.quarkus\:camel-quarkus-integration-tests-support-grpc"=org/acme/proto/d/*,org/acme/proto/d/sub/proto-d-2.proto,org/acme/proto/d/sub/package**
+
+# Test excluding unwanted services
+quarkus.camel.grpc.service-excludes=org.acme.proto.f.TestFGrpc*,org.acme.proto.f.sub.*,org.acme.proto.f.sub.**
diff --git 
a/integration-tests/grpc/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
index ddd6fd6cfe..33c5955058 100644
--- 
a/integration-tests/grpc/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
@@ -65,6 +65,7 @@ import static 
org.apache.camel.quarkus.component.grpc.it.PingPongImpl.GRPC_TEST_
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -601,6 +602,21 @@ class GrpcTest {
         }
     }
 
+    @Test
+    public void serviceExcludes() {
+        JsonPath result = RestAssured.get("/grpc/services")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        List<String> services = result.getList(".");
+        assertFalse(services.isEmpty());
+        assertTrue(services.stream().anyMatch(service -> 
service.startsWith("org.acme.proto")));
+        assertTrue(services.stream().noneMatch(service -> 
service.startsWith("org.acme.proto.f")));
+    }
+
     static Stream<Arguments> producerMethodPorts() {
         return Stream.of(
                 Arguments.of("pingSyncSync", 
"{{camel.grpc.test.async.server.port}}"),

Reply via email to