This is an automated email from the ASF dual-hosted git repository. github-bot pushed a commit to branch camel-master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 673bae5de429a08735139f3a652bd6fe67116bac Author: James Netherton <jamesnether...@gmail.com> AuthorDate: Wed Dec 2 10:41:18 2020 +0000 Google PubSub native support Fixes #1041 --- .../pages/reference/extensions/google-pubsub.adoc | 18 ++- .../reference/components/google-pubsub.adoc | 6 +- .../google-pubsub/integration-test/pom.xml | 66 --------- .../google/pubsub/it/GooglePubsubResource.java | 51 ------- extensions-jvm/pom.xml | 1 - .../google-pubsub/deployment/pom.xml | 8 + .../pubsub/deployment/GooglePubsubProcessor.java | 32 ++-- .../google-pubsub/pom.xml | 1 - .../google-pubsub/runtime/pom.xml | 21 ++- .../runtime/src/main/doc/limitations.adoc | 6 + .../google/pubsub/GooglePubsubRecorder.java | 41 ++++++ .../pubsub/JacksonGooglePubsubSerializer.java | 29 ++-- .../main/resources/META-INF/quarkus-extension.yaml | 3 +- extensions/pom.xml | 1 + integration-tests/google-pubsub/pom.xml | 122 ++++++++++++++++ .../quarkus/component/google/pubsub/it/Fruit.java | 22 +-- .../google/pubsub/it/GooglePubsubResource.java | 70 +++++++++ .../component/google/pubsub/it/GooglePubsubIT.java | 15 +- .../google/pubsub/it/GooglePubsubTest.java | 34 ++++- .../google/pubsub/it/GooglePubsubTestResource.java | 161 +++++++++++++++++++++ integration-tests/pom.xml | 1 + pom.xml | 6 +- poms/bom/pom.xml | 28 ++-- tooling/scripts/test-categories.yaml | 1 + 24 files changed, 554 insertions(+), 190 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/google-pubsub.adoc b/docs/modules/ROOT/pages/reference/extensions/google-pubsub.adoc index d2f1acc..cf1d22b 100644 --- a/docs/modules/ROOT/pages/reference/extensions/google-pubsub.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/google-pubsub.adoc @@ -3,15 +3,15 @@ = Google Pubsub :page-aliases: extensions/google-pubsub.adoc :cq-artifact-id: camel-quarkus-google-pubsub -:cq-native-supported: false -:cq-status: Preview +:cq-native-supported: true +:cq-status: Stable :cq-description: Send and receive messages to/from Google Cloud Platform PubSub Service. :cq-deprecated: false :cq-jvm-since: 1.0.0 -:cq-native-since: 1.0.0 +:cq-native-since: 1.5.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.5.0## Send and receive messages to/from Google Cloud Platform PubSub Service. @@ -32,3 +32,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. + +== Camel Quarkus limitations + +By default, the Camel PubSub component uses JDK object serialization via `ObjectOutputStream` whenever the message body is anything other than `String` or `byte[]`. + +Since such serialization is not yet supported by GraalVM, this extension provides a custom Jackson based serializer to serialize complex message payloads as JSON. + +If your payload contains binary data, then you will need to handle that by creating a custom Jackson Serializer / Deserializer. Refer to the https://quarkus.io/guides/writing-extensions#customizing-jackson[Quarkus Jackson guide] for +information on how to do this. + diff --git a/docs/modules/ROOT/partials/reference/components/google-pubsub.adoc b/docs/modules/ROOT/partials/reference/components/google-pubsub.adoc index 4a45c2c..8725241 100644 --- a/docs/modules/ROOT/partials/reference/components/google-pubsub.adoc +++ b/docs/modules/ROOT/partials/reference/components/google-pubsub.adoc @@ -2,11 +2,11 @@ // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page :cq-artifact-id: camel-quarkus-google-pubsub :cq-artifact-id-base: google-pubsub -: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 +:cq-native-since: 1.5.0 :cq-camel-part-name: google-pubsub :cq-camel-part-title: Google Pubsub :cq-camel-part-description: Send and receive messages to/from Google Cloud Platform PubSub Service. diff --git a/extensions-jvm/google-pubsub/integration-test/pom.xml b/extensions-jvm/google-pubsub/integration-test/pom.xml deleted file mode 100644 index af13b7c..0000000 --- a/extensions-jvm/google-pubsub/integration-test/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - 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. - ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-build-parent-it</artifactId> - <version>1.5.0-SNAPSHOT</version> - <relativePath>../../../poms/build-parent-it/pom.xml</relativePath> - </parent> - - <artifactId>camel-quarkus-google-pubsub-integration-test</artifactId> - <name>Camel Quarkus :: Google Pubsub :: Integration Test</name> - <description>Integration tests for Camel Quarkus Google Pubsub 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-google-pubsub-deployment</mvnd.builder.rule> - </properties> - - <dependencies> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-google-pubsub</artifactId> - </dependency> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-resteasy</artifactId> - </dependency> - - <!-- test dependencies --> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-junit5</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>io.rest-assured</groupId> - <artifactId>rest-assured</artifactId> - <scope>test</scope> - </dependency> - </dependencies> - -</project> diff --git a/extensions-jvm/google-pubsub/integration-test/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java b/extensions-jvm/google-pubsub/integration-test/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java deleted file mode 100644 index 39aa2f3..0000000 --- a/extensions-jvm/google-pubsub/integration-test/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java +++ /dev/null @@ -1,51 +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.google.pubsub.it; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.apache.camel.CamelContext; -import org.jboss.logging.Logger; - -@Path("/google-pubsub") -@ApplicationScoped -public class GooglePubsubResource { - - private static final Logger LOG = Logger.getLogger(GooglePubsubResource.class); - - private static final String COMPONENT_GOOGLE_PUBSUB = "google-pubsub"; - @Inject - CamelContext context; - - @Path("/load/component/google-pubsub") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Response loadComponentGooglePubsub() throws Exception { - /* This is an autogenerated test */ - if (context.getComponent(COMPONENT_GOOGLE_PUBSUB) != null) { - return Response.ok().build(); - } - LOG.warnf("Could not load [%s] from the Camel context", COMPONENT_GOOGLE_PUBSUB); - return Response.status(500, COMPONENT_GOOGLE_PUBSUB + " could not be loaded from the Camel context").build(); - } -} diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index 4eef5cb..24750af 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -72,7 +72,6 @@ <module>freemarker</module> <module>ganglia</module> <module>google-bigquery</module> - <module>google-pubsub</module> <module>groovy</module> <module>guava-eventbus</module> <module>hazelcast</module> diff --git a/extensions-jvm/google-pubsub/deployment/pom.xml b/extensions/google-pubsub/deployment/pom.xml similarity index 88% rename from extensions-jvm/google-pubsub/deployment/pom.xml rename to extensions/google-pubsub/deployment/pom.xml index 4be7c3b..023d43b 100644 --- a/extensions-jvm/google-pubsub/deployment/pom.xml +++ b/extensions/google-pubsub/deployment/pom.xml @@ -31,6 +31,14 @@ <dependencies> <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jackson-deployment</artifactId> + </dependency> + <dependency> + <groupId>io.quarkiverse.googlecloudservices</groupId> + <artifactId>quarkus-google-cloud-pubsub-deployment</artifactId> + </dependency> + <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-core-deployment</artifactId> </dependency> diff --git a/extensions-jvm/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java b/extensions/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java similarity index 51% rename from extensions-jvm/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java rename to extensions/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java index 40fea4d..2377149 100644 --- a/extensions-jvm/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java +++ b/extensions/google-pubsub/deployment/src/main/java/org/apache/camel/quarkus/component/google/pubsub/deployment/GooglePubsubProcessor.java @@ -16,17 +16,20 @@ */ package org.apache.camel.quarkus.component.google.pubsub.deployment; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.arc.deployment.UnremovableBeanBuildItem; +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.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; -import org.apache.camel.quarkus.core.JvmOnlyRecorder; -import org.jboss.logging.Logger; +import io.quarkus.jackson.ObjectMapperProducer; +import org.apache.camel.component.google.pubsub.serializer.GooglePubsubSerializer; +import org.apache.camel.quarkus.component.google.pubsub.GooglePubsubRecorder; +import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBeanBuildItem; class GooglePubsubProcessor { - private static final Logger LOG = Logger.getLogger(GooglePubsubProcessor.class); private static final String FEATURE = "camel-google-pubsub"; @BuildStep @@ -34,13 +37,18 @@ class GooglePubsubProcessor { 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 + @BuildStep + public void markObjectMapperUnremovable(BuildProducer<UnremovableBeanBuildItem> unremovable) { + unremovable.produce(new UnremovableBeanBuildItem( + new UnremovableBeanBuildItem.BeanClassNameExclusion(ObjectMapper.class.getName()))); + unremovable.produce(new UnremovableBeanBuildItem( + new UnremovableBeanBuildItem.BeanClassNameExclusion(ObjectMapperProducer.class.getName()))); + } + + @BuildStep + @Record(ExecutionTime.RUNTIME_INIT) + public CamelRuntimeBeanBuildItem createGooglePubsubSerializerBean(GooglePubsubRecorder recorder) { + return new CamelRuntimeBeanBuildItem("googlePubsubSerializer", GooglePubsubSerializer.class.getTypeName(), + recorder.createSerializer()); } } diff --git a/extensions-jvm/google-pubsub/pom.xml b/extensions/google-pubsub/pom.xml similarity index 97% rename from extensions-jvm/google-pubsub/pom.xml rename to extensions/google-pubsub/pom.xml index 870c27f..d7dbb0b 100644 --- a/extensions-jvm/google-pubsub/pom.xml +++ b/extensions/google-pubsub/pom.xml @@ -33,6 +33,5 @@ <modules> <module>deployment</module> <module>runtime</module> - <module>integration-test</module> </modules> </project> diff --git a/extensions-jvm/google-pubsub/runtime/pom.xml b/extensions/google-pubsub/runtime/pom.xml similarity index 82% rename from extensions-jvm/google-pubsub/runtime/pom.xml rename to extensions/google-pubsub/runtime/pom.xml index 3ef7db4..26548f6 100644 --- a/extensions-jvm/google-pubsub/runtime/pom.xml +++ b/extensions/google-pubsub/runtime/pom.xml @@ -31,7 +31,7 @@ <properties> <camel.quarkus.jvmSince>1.0.0</camel.quarkus.jvmSince> - <camel.quarkus.nativeSince>1.0.0</camel.quarkus.nativeSince> + <camel.quarkus.nativeSince>1.5.0</camel.quarkus.nativeSince> </properties> <dependencyManagement> @@ -43,11 +43,30 @@ <type>pom</type> <scope>import</scope> </dependency> + <!-- https://github.com/micrometer-metrics/micrometer/issues/2249 --> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-micrometer</artifactId> + <exclusions> + <exclusion> + <groupId>com.google.cloud</groupId> + <artifactId>google-cloud-monitoring</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jackson</artifactId> + </dependency> + <dependency> + <groupId>io.quarkiverse.googlecloudservices</groupId> + <artifactId>quarkus-google-cloud-pubsub</artifactId> + </dependency> + <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-core</artifactId> </dependency> diff --git a/extensions/google-pubsub/runtime/src/main/doc/limitations.adoc b/extensions/google-pubsub/runtime/src/main/doc/limitations.adoc new file mode 100644 index 0000000..49606e0 --- /dev/null +++ b/extensions/google-pubsub/runtime/src/main/doc/limitations.adoc @@ -0,0 +1,6 @@ +By default, the Camel PubSub component uses JDK object serialization via `ObjectOutputStream` whenever the message body is anything other than `String` or `byte[]`. + +Since such serialization is not yet supported by GraalVM, this extension provides a custom Jackson based serializer to serialize complex message payloads as JSON. + +If your payload contains binary data, then you will need to handle that by creating a custom Jackson Serializer / Deserializer. Refer to the https://quarkus.io/guides/writing-extensions#customizing-jackson[Quarkus Jackson guide] for +information on how to do this. diff --git a/extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/GooglePubsubRecorder.java b/extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/GooglePubsubRecorder.java new file mode 100644 index 0000000..a9dd14e --- /dev/null +++ b/extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/GooglePubsubRecorder.java @@ -0,0 +1,41 @@ +/* + * 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.google.pubsub; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.arc.Arc; +import io.quarkus.arc.InstanceHandle; +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.annotations.Recorder; +import org.apache.camel.component.google.pubsub.serializer.GooglePubsubSerializer; + +@Recorder +public class GooglePubsubRecorder { + + public RuntimeValue<GooglePubsubSerializer> createSerializer() { + GooglePubsubSerializer serializer = new JacksonGooglePubsubSerializer(getObjectMapper()); + return new RuntimeValue<>(serializer); + } + + private ObjectMapper getObjectMapper() { + InstanceHandle<ObjectMapper> instance = Arc.container().instance(ObjectMapper.class); + if (instance.isAvailable()) { + return instance.get(); + } + return new ObjectMapper(); + } +} diff --git a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java b/extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/JacksonGooglePubsubSerializer.java similarity index 50% copy from extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java copy to extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/JacksonGooglePubsubSerializer.java index 9987659..696267b 100644 --- a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java +++ b/extensions/google-pubsub/runtime/src/main/java/org/apache/camel/quarkus/component/google/pubsub/JacksonGooglePubsubSerializer.java @@ -14,20 +14,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.google.pubsub.it; +package org.apache.camel.quarkus.component.google.pubsub; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import java.io.IOException; -@QuarkusTest -class GooglePubsubTest { +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.component.google.pubsub.serializer.GooglePubsubSerializer; - @Test - public void loadComponentGooglePubsub() { - RestAssured.get("/google-pubsub/load/component/google-pubsub") - .then() - .statusCode(200); +/** + * A Jackson implementation of {@link GooglePubsubSerializer} which serializes a given payload to JSON instead of + * the default implementation that uses (unsuitable for native mode) JDK object serialization. + */ +public class JacksonGooglePubsubSerializer implements GooglePubsubSerializer { + + private final ObjectMapper mapper; + + public JacksonGooglePubsubSerializer(ObjectMapper mapper) { + this.mapper = mapper; } + @Override + public byte[] serialize(Object payload) throws IOException { + return this.mapper.writeValueAsBytes(payload); + } } diff --git a/extensions-jvm/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 97% rename from extensions-jvm/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 715af95..9c721ea 100644 --- a/extensions-jvm/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/google-pubsub/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -24,9 +24,8 @@ name: "Camel Google Pubsub" description: "Send and receive messages to/from Google Cloud Platform PubSub Service" metadata: - unlisted: true guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/google-pubsub.html" categories: - "integration" status: - - "preview" + - "stable" diff --git a/extensions/pom.xml b/extensions/pom.xml index a29085f..9beeb7c 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -112,6 +112,7 @@ <module>google-calendar</module> <module>google-drive</module> <module>google-mail</module> + <module>google-pubsub</module> <module>google-sheets</module> <module>graphql</module> <module>grok</module> diff --git a/integration-tests/google-pubsub/pom.xml b/integration-tests/google-pubsub/pom.xml new file mode 100644 index 0000000..64533e4 --- /dev/null +++ b/integration-tests/google-pubsub/pom.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-tests</artifactId> + <version>1.5.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-quarkus-integration-test-google-pubsub</artifactId> + <name>Camel Quarkus :: Integration Tests :: Google Pubsub</name> + <description>Integration tests for Camel Quarkus Google Pubsub extension</description> + + <dependencies> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-main</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-google-pubsub</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy</artifactId> + </dependency> + + <!-- test dependencies --> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-testcontainers-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-google-pubsub-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-main-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <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/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java b/integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/Fruit.java similarity index 72% copy from extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java copy to integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/Fruit.java index 9987659..1de6e4e 100644 --- a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java +++ b/integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/Fruit.java @@ -16,18 +16,20 @@ */ package org.apache.camel.quarkus.component.google.pubsub.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.quarkus.runtime.annotations.RegisterForReflection; -@QuarkusTest -class GooglePubsubTest { +@RegisterForReflection +public class Fruit { - @Test - public void loadComponentGooglePubsub() { - RestAssured.get("/google-pubsub/load/component/google-pubsub") - .then() - .statusCode(200); + @JsonProperty + private String name; + + public Fruit(String name) { + this.name = name; } + public String getName() { + return name; + } } diff --git a/integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java b/integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java new file mode 100644 index 0000000..86fe059 --- /dev/null +++ b/integration-tests/google-pubsub/src/main/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubResource.java @@ -0,0 +1,70 @@ +/* + * 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.google.pubsub.it; + +import java.net.URI; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.camel.ConsumerTemplate; +import org.apache.camel.ProducerTemplate; + +@Path("/google-pubsub") +public class GooglePubsubResource { + + @Inject + ProducerTemplate producerTemplate; + + @Inject + ConsumerTemplate consumerTemplate; + + @POST + public Response sendStringToTopic(String message) { + producerTemplate.sendBody("google-pubsub:{{project.id}}:{{topic.name}}", message); + return Response.created(URI.create("https://camel.apache.org")).build(); + } + + @GET + public Response consumeStringFromTopic() { + Object response = consumerTemplate + .receiveBody("google-pubsub:{{project.id}}:{{subscription.name}}?synchronousPull=true", 5000L); + return Response.ok(response).build(); + } + + @Path("/pojo") + @POST + public Response sendPojoToTopic(String fruitName) { + Fruit fruit = new Fruit(fruitName); + producerTemplate.sendBody("google-pubsub:{{project.id}}:{{topic.name}}", fruit); + return Response.created(URI.create("https://camel.apache.org")).build(); + } + + @Path("/pojo") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response consumePojoFromTopic() { + Object response = consumerTemplate + .receiveBody("google-pubsub:{{project.id}}:{{subscription.name}}?synchronousPull=true", 5000L); + return Response.ok(response).build(); + } +} diff --git a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubIT.java similarity index 71% copy from extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java copy to integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubIT.java index 9987659..d8aac91 100644 --- a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java +++ b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubIT.java @@ -16,18 +16,9 @@ */ package org.apache.camel.quarkus.component.google.pubsub.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import io.quarkus.test.junit.NativeImageTest; -@QuarkusTest -class GooglePubsubTest { - - @Test - public void loadComponentGooglePubsub() { - RestAssured.get("/google-pubsub/load/component/google-pubsub") - .then() - .statusCode(200); - } +@NativeImageTest +class GooglePubsubIT extends GooglePubsubTest { } diff --git a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java similarity index 53% rename from extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java rename to integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java index 9987659..0073390 100644 --- a/extensions-jvm/google-pubsub/integration-test/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java +++ b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTest.java @@ -16,18 +16,46 @@ */ package org.apache.camel.quarkus.component.google.pubsub.it; +import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import org.junit.jupiter.api.Test; +import static org.hamcrest.CoreMatchers.is; + @QuarkusTest +@QuarkusTestResource(GooglePubsubTestResource.class) class GooglePubsubTest { @Test - public void loadComponentGooglePubsub() { - RestAssured.get("/google-pubsub/load/component/google-pubsub") + public void pubsubTopicProduceConsume() { + String message = "Hello Camel Quarkus Google PubSub"; + + RestAssured.given() + .body(message) + .post("/google-pubsub") .then() - .statusCode(200); + .statusCode(201); + + RestAssured.get("/google-pubsub") + .then() + .statusCode(200) + .body(is(message)); } + @Test + public void jacksonSerializer() { + String fruitName = "Apple"; + + RestAssured.given() + .body(fruitName) + .post("/google-pubsub/pojo") + .then() + .statusCode(201); + + RestAssured.get("/google-pubsub/pojo") + .then() + .statusCode(200) + .body("name", is(fruitName)); + } } diff --git a/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTestResource.java b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTestResource.java new file mode 100644 index 0000000..4e27bd5 --- /dev/null +++ b/integration-tests/google-pubsub/src/test/java/org/apache/camel/quarkus/component/google/pubsub/it/GooglePubsubTestResource.java @@ -0,0 +1,161 @@ +/* + * 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.google.pubsub.it; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.rpc.FixedTransportChannelProvider; +import com.google.cloud.pubsub.v1.SubscriptionAdminClient; +import com.google.cloud.pubsub.v1.SubscriptionAdminSettings; +import com.google.cloud.pubsub.v1.TopicAdminClient; +import com.google.cloud.pubsub.v1.TopicAdminSettings; +import com.google.pubsub.v1.ProjectSubscriptionName; +import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.Topic; +import com.google.pubsub.v1.TopicName; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import org.apache.camel.util.CollectionHelper; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; + +public class GooglePubsubTestResource implements QuarkusTestResourceLifecycleManager { + + private static final String PROJECT_ID = "test-project"; + private static final String TOPIC = "test-topic"; + private static final String SUBSCRIPTION = TOPIC + "-subscription"; + private static final String GOOGLE_PUBSUB_IMAGE = "google/cloud-sdk:latest"; + private static final int GOOGLE_PUBSUB_PORT = 8383; + + private GenericContainer<?> container; + + @Override + public Map<String, String> start() { + try { + container = new GenericContainer<>(GOOGLE_PUBSUB_IMAGE) + .withCommand("/bin/sh", "-c", + String.format("gcloud beta emulators pubsub start --project %s --host-port=0.0.0.0:%d", + PROJECT_ID, GOOGLE_PUBSUB_PORT)) + .withExposedPorts(GOOGLE_PUBSUB_PORT) + .waitingFor(new LogMessageWaitStrategy().withRegEx("(?s).*started.*$")); + + container.start(); + + createTopicSubscriptionPair(TOPIC, SUBSCRIPTION); + + String endpointAddress = String.format("%s:%s", container.getContainerIpAddress(), container.getFirstMappedPort()); + + return CollectionHelper.mapOf( + "project.id", PROJECT_ID, + "topic.name", TOPIC, + "subscription.name", SUBSCRIPTION, + "camel.component.google-pubsub.endpoint", endpointAddress); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void stop() { + try { + if (container != null) { + container.stop(); + } + } catch (Exception e) { + // ignored + } + } + + public void createTopicSubscriptionPair(String topicName, String subscriptionName) throws InterruptedException { + TopicName projectTopicName = TopicName.of(PROJECT_ID, topicName); + ProjectSubscriptionName projectSubscriptionName = ProjectSubscriptionName.of(PROJECT_ID, subscriptionName); + + Topic topic = Topic.newBuilder().setName(projectTopicName.toString()).build(); + Subscription subscription = Subscription.newBuilder() + .setName(projectSubscriptionName.toString()) + .setTopic(topic.getName()) + .setAckDeadlineSeconds(10) + .build(); + + createTopicSubscriptionPair(topic, subscription); + } + + public void createTopicSubscriptionPair(Topic topic, Subscription subscription) throws InterruptedException { + createTopic(topic); + createSubscription(subscription); + } + + public void createTopic(Topic topic) throws InterruptedException { + TopicAdminClient topicAdminClient = createTopicAdminClient(); + topicAdminClient.createTopic(topic); + topicAdminClient.shutdown(); + topicAdminClient.awaitTermination(5, TimeUnit.SECONDS); + } + + public void createSubscription(Subscription subscription) throws InterruptedException { + SubscriptionAdminClient subscriptionAdminClient = createSubscriptionAdminClient(); + subscriptionAdminClient.createSubscription(subscription); + subscriptionAdminClient.shutdown(); + subscriptionAdminClient.awaitTermination(5, TimeUnit.SECONDS); + } + + private FixedTransportChannelProvider createChannelProvider() { + Integer port = container.getFirstMappedPort(); + ManagedChannel channel = ManagedChannelBuilder + .forTarget(String.format("%s:%s", "localhost", port)) + .usePlaintext() + .build(); + + return FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)); + } + + private TopicAdminClient createTopicAdminClient() { + FixedTransportChannelProvider channelProvider = createChannelProvider(); + CredentialsProvider credentialsProvider = NoCredentialsProvider.create(); + + try { + return TopicAdminClient.create( + TopicAdminSettings.newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private SubscriptionAdminClient createSubscriptionAdminClient() { + FixedTransportChannelProvider channelProvider = createChannelProvider(); + CredentialsProvider credentialsProvider = NoCredentialsProvider.create(); + + try { + return SubscriptionAdminClient.create( + SubscriptionAdminSettings.newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 1326867..a37f22f 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -99,6 +99,7 @@ <module>git</module> <module>github</module> <module>google</module> + <module>google-pubsub</module> <module>graphql</module> <module>grok</module> <module>grpc</module> diff --git a/pom.xml b/pom.xml index 411a804..a67ae8e 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ <jodatime.version>2.10.6</jodatime.version><!-- Mess in transitive dependencies of Spark and Splunk --> <github-api.version>1.111</github-api.version> <google-http-client.version>1.34.0</google-http-client.version> - <google-api-common.version>1.9.0</google-api-common.version><!-- Mess in pubsub transitive deps vs google cloud deps --> + <google-auth-library-oauth2-http.version>0.21.1</google-auth-library-oauth2-http.version> <!-- Mess in google-cloud-bom --> <guava.version>29.0-jre</guava.version> <gson.version>2.8.5</gson.version> <hadoop2.version>${hadoop2-version}</hadoop2.version><!-- Spark --> @@ -84,9 +84,9 @@ <nimbus-jose-jwt.version>4.41.1</nimbus-jose-jwt.version><!-- Mess in hdfs transitive deps --> <okhttp.version>${squareup-okhttp-version}</okhttp.version><!-- keep in sync with okio --> <okio.version>${squareup-okio-version}</okio.version><!-- keep in sync with okhttp --> - <opencensus-api.version>0.26.0</opencensus-api.version><!-- Mess in pubsub transitive deps vs google cloud deps --> <optaplanner.version>7.46.0.Final</optaplanner.version> <quarkus.version>1.10.2.Final</quarkus.version> + <quarkus-google-cloud.version>0.2.0</quarkus-google-cloud.version> <quarkus-qpid-jms.version>0.21.0</quarkus-qpid-jms.version> <protobuf.version>${protobuf-version}</protobuf.version> <retrofit.version>2.5.0</retrofit.version> @@ -128,8 +128,6 @@ <exec-maven-plugin.version>3.0.0</exec-maven-plugin.version> <formatter-maven-plugin.version>2.11.0</formatter-maven-plugin.version> <frontend-maven-plugin.version>1.6</frontend-maven-plugin.version> - <google-auth-library-credentials.version>0.19.0</google-auth-library-credentials.version> - <google-auth-library-oauth2-http.version>0.19.0</google-auth-library-oauth2-http.version> <groovy-maven-plugin.version>2.1.1</groovy-maven-plugin.version> <groovy.version>3.0.5</groovy.version> <impsort-maven-plugin.version>1.3.2</impsort-maven-plugin.version> diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml index ac6aef3..3f93063 100644 --- a/poms/bom/pom.xml +++ b/poms/bom/pom.xml @@ -906,6 +906,16 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-google-pubsub</artifactId> <version>${camel.version}</version> + <exclusions> + <exclusion> + <groupId>com.google.cloud</groupId> + <artifactId>google-cloud-pubsub</artifactId> + </exclusion> + <exclusion> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.apache.camel</groupId> @@ -5366,11 +5376,6 @@ </exclusions> </dependency> <dependency> - <groupId>com.google.api</groupId> - <artifactId>api-common</artifactId> - <version>${google-api-common.version}</version> - </dependency> - <dependency> <groupId>com.google.api.grpc</groupId> <artifactId>proto-google-common-protos</artifactId> <version>${proto-google-common-protos.version}</version> @@ -5378,7 +5383,7 @@ <dependency> <groupId>com.google.auth</groupId> <artifactId>google-auth-library-credentials</artifactId> - <version>${google-auth-library-credentials.version}</version> + <version>${google-auth-library-oauth2-http.version}</version> </dependency> <dependency> <groupId>com.google.auth</groupId> @@ -5523,9 +5528,14 @@ <version>${debezium.version}</version> </dependency> <dependency> - <groupId>io.opencensus</groupId> - <artifactId>opencensus-api</artifactId> - <version>${opencensus-api.version}</version> + <groupId>io.quarkiverse.googlecloudservices</groupId> + <artifactId>quarkus-google-cloud-pubsub</artifactId> + <version>${quarkus-google-cloud.version}</version> + </dependency> + <dependency> + <groupId>io.quarkiverse.googlecloudservices</groupId> + <artifactId>quarkus-google-cloud-pubsub-deployment</artifactId> + <version>${quarkus-google-cloud.version}</version> </dependency> <dependency> <groupId>io.smallrye.reactive</groupId> diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index ad30217..ad5c6fa 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -30,6 +30,7 @@ cloud: - azure - consul - elasticsearch-rest + - google-pubsub - grpc - protobuf - smallrye-reactive-messaging