You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2021/07/26 20:27:41 UTC

[camel-quarkus] branch main updated: Stress the more preferred way of configuring components via CDI by moving it up

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 7a0df68  Stress the more preferred way of configuring components via CDI by moving it up
7a0df68 is described below

commit 7a0df68646419f7927eaf4ddec141a6bcfeb652e
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Mon Jul 26 18:24:03 2021 +0200

    Stress the more preferred way of configuring components via CDI by moving it up
---
 .../ROOT/pages/user-guide/configuration.adoc       | 69 ++++++++++++++--------
 .../camel/quarkus/component/mock/it/CdiConfig.java | 52 ++++++++++++++++
 .../quarkus/component/mock/it/MockResource.java    |  9 +++
 .../component/mock/it/MockRouteBuilder.java        | 12 ++++
 .../camel/quarkus/component/mock/it/MockTest.java  | 12 ++++
 5 files changed, 129 insertions(+), 25 deletions(-)

diff --git a/docs/modules/ROOT/pages/user-guide/configuration.adoc b/docs/modules/ROOT/pages/user-guide/configuration.adoc
index f42be4c..0bded8c 100644
--- a/docs/modules/ROOT/pages/user-guide/configuration.adoc
+++ b/docs/modules/ROOT/pages/user-guide/configuration.adoc
@@ -40,7 +40,49 @@ camel.component.log.exchange-formatter.show-body-type = false
 
 === CDI
 
-The same can be done programmatically using CDI:
+The same can be done programmatically using CDI.
+
+The best way is to observe the `ComponentAddEvent` and configure the component before the routes and the `CamelContext` are started:
+
+[source,java]
+----
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import org.apache.camel.quarkus.core.events.ComponentAddEvent;
+import org.apache.camel.component.log.LogComponent;
+import org.apache.camel.support.processor.DefaultExchangeFormatter;
+
+@ApplicationScoped
+public static class EventHandler {
+    public void onComponentAdd(@Observes ComponentAddEvent event) {
+        if (event.getComponent() instanceof LogComponent) {
+            /* Perform some custom configuration of the component */
+            LogComponent logComponent = ((LogComponent) event.getComponent());
+            DefaultExchangeFormatter formatter = new DefaultExchangeFormatter();
+            formatter.setShowExchangePattern(false);
+            formatter.setShowBodyType(false);
+            logComponent.setExchangeFormatter(formatter);
+        }
+    }
+}
+----
+
+==== Producing a `@Named` component instance
+
+Alternatively, you could create and configure the component yourself in a `@Named` producer method.
+This would work thanks to the fact that Camel uses the component URI scheme to look-up components from its registry.
+E.g. for `LogComponent` it would look for a `log` named bean.
+
+[WARNING]
+====
+Please note that while producing a `@Named` component bean will work in most cases, it may cause subtle issues with some components.
+Camel Quarkus extensions may do one or more of the following:
++
+* Pass custom subtype of the default Camel component type - see e.g. in https://github.com/apache/camel-quarkus/blob/main/extensions/vertx-websocket/runtime/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/VertxWebsocketRecorder.java#L42[Vert.x WebSocket extension]
+* Perform some Quarkus specific customization of the component - see e.g. in https://github.com/apache/camel-quarkus/blob/main/extensions/jpa/runtime/src/main/java/org/apache/camel/quarkus/component/jpa/CamelJpaRecorder.java#L35[JPA extension].
++
+All of these get lost when you produce your own component instance. Therefore configuring components in an observer method should be preferred.
+====
 
 [source,java]
 ----
@@ -68,30 +110,7 @@ public class Configurations {
     }
 }
 ----
-<1> Camel uses the component URI scheme to look-up components from its registry, this requires you to add the `@Named` annotation to the method, otherwise the CDI container would create an anonymous bean and Camel would not be able to look it up.
-The `"log"` argument of the `@Named` annotation can be omitted as long as the name of the method is the same.
-
-In Camel Quarkus, the Camel components are discovered during the augmentation phase.
-Hence producing a new component as shown in the example above would invalidate any optimization that may have been made.
-
-As a better alternative you can use `@Inject` to obtain an instance of a component automatically created by Camel or you can observe one of the https://github.com/apache/camel-quarkus/tree/main/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/events[events] fired by Camel Quarkus as shown in the following example, in which we use `@Observes` to be notified about components added to the Camel Context:
-
-[source,java]
-----
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.event.Observes;
-import org.apache.camel.quarkus.core.events.ComponentAddEvent;
-import org.apache.camel.component.log.LogComponent;
-
-@ApplicationScoped
-public static class EventHandler {
-    public void onComponentAdd(@Observes ComponentAddEvent event) {
-        if (event.getComponent() instanceof LogComponent) {
-            // do something with the log component
-        }
-    }
-}
-----
+<1> The `"log"` argument of the `@Named` annotation can be omitted as long as the name of the method is the same.
 
 == Configuration by convention
 
diff --git a/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/CdiConfig.java b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/CdiConfig.java
new file mode 100644
index 0000000..9097371
--- /dev/null
+++ b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/CdiConfig.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mock.it;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+
+import org.apache.camel.component.mock.MockComponent;
+import org.apache.camel.quarkus.core.events.ComponentAddEvent;
+import org.apache.camel.spi.CamelEvent.CamelContextStartedEvent;
+import org.jboss.logging.Logger;
+
+@ApplicationScoped
+public class CdiConfig {
+    private static final Logger LOG = Logger.getLogger(CdiConfig.class);
+
+    private final AtomicBoolean contextStarted = new AtomicBoolean(false);
+
+    public void configureMock(@Observes ComponentAddEvent event) {
+        if (event.getComponent() instanceof MockComponent) {
+            LOG.info("Customizing the MockComponent");
+            MockComponent mockComponent = (MockComponent) event.getComponent();
+            assert !mockComponent.isLog();
+            /* Perform some custom configuration of the component */
+            mockComponent.setLog(true);
+            /* Make sure that what we say in docs/modules/ROOT/pages/user-guide/configuration.adoc is true */
+            assert !contextStarted.get();
+        }
+    }
+
+    public void contextStarted(@Observes CamelContextStartedEvent event) {
+        LOG.info("Camel context started");
+        contextStarted.set(true);
+    }
+
+}
diff --git a/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockResource.java b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockResource.java
index 351c175..11e3101 100644
--- a/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockResource.java
+++ b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockResource.java
@@ -22,6 +22,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
 
 import org.apache.camel.CamelContext;
@@ -100,4 +101,12 @@ public class MockResource {
 
         mockEndpoint.assertIsSatisfied();
     }
+
+    @Path("/route/{route}")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    public String post(String message, @PathParam("route") String route) throws Exception {
+        return producerTemplate.requestBody("direct:" + route, message, String.class);
+    }
+
 }
diff --git a/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockRouteBuilder.java b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockRouteBuilder.java
index 66685ce..de30ff2 100644
--- a/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockRouteBuilder.java
+++ b/integration-test-groups/foundation/mock/src/main/java/org/apache/camel/quarkus/component/mock/it/MockRouteBuilder.java
@@ -16,12 +16,20 @@
  */
 package org.apache.camel.quarkus.component.mock.it;
 
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockComponent;
 import org.jboss.logging.Logger;
 
+@ApplicationScoped
 public class MockRouteBuilder extends RouteBuilder {
     private static final Logger LOG = Logger.getLogger(MockRouteBuilder.class);
 
+    @Inject
+    MockComponent mock;
+
     @Override
     public void configure() {
         from("direct:mockStart")
@@ -33,5 +41,9 @@ public class MockRouteBuilder extends RouteBuilder {
         from("direct:mockFoo")
                 .process(e -> LOG.info("mockFoo:" + e.getMessage().getBody(String.class)))
                 .transform(constant("Bye World"));
+
+        from("direct:cdiConfig")
+                .setBody(e -> "mockComponent.log = " + mock.isLog());
+
     }
 }
diff --git a/integration-test-groups/foundation/mock/src/test/java/org/apache/camel/quarkus/component/mock/it/MockTest.java b/integration-test-groups/foundation/mock/src/test/java/org/apache/camel/quarkus/component/mock/it/MockTest.java
index 089ed44..9f97ead 100644
--- a/integration-test-groups/foundation/mock/src/test/java/org/apache/camel/quarkus/component/mock/it/MockTest.java
+++ b/integration-test-groups/foundation/mock/src/test/java/org/apache/camel/quarkus/component/mock/it/MockTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.quarkus.component.mock.it;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
+import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Test;
 
 @QuarkusTest
@@ -42,4 +43,15 @@ class MockTest {
                 .statusCode(204);
     }
 
+    @Test
+    public void cdiConfig() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("foo")
+                .post("/mock/route/cdiConfig")
+                .then()
+                .statusCode(200)
+                .body(Matchers.is("mockComponent.log = true"));
+    }
+
 }