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/12/03 07:57:21 UTC

[camel-quarkus] branch camel-master updated (7885e9c -> 417bc87)

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

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


 discard 7885e9c  Google PubSub native support
     new 417bc87  Google PubSub native support

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (7885e9c)
            \
             N -- N -- N   refs/heads/camel-master (417bc87)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 docs/modules/ROOT/pages/reference/extensions/google-pubsub.adoc | 3 ++-
 extensions/google-pubsub/runtime/src/main/doc/limitations.adoc  | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)


[camel-quarkus] 01/01: Google PubSub native support

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 417bc874def19d3338895ea2b3cff1ef9ff4bf56
Author: James Netherton <ja...@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 dbb2244..f15f0dc 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 2782fa9..10c049e 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 9cafa30..8586101 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 92b950e..11e4b3d 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>
@@ -5360,11 +5370,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>
@@ -5372,7 +5377,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>
@@ -5517,9 +5522,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 7941fd7..385bc2c 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