Repository: camel
Updated Branches:
  refs/heads/camel-2.17.x 1b47ca4b2 -> b340d6990


CAMEL-9904: Avoid creating an empty default Camel context in Camel CDI for 
empty deployments


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b340d699
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b340d699
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b340d699

Branch: refs/heads/camel-2.17.x
Commit: b340d69906c84370a7d6025e079c8fb7858037fd
Parents: 1b47ca4
Author: Antonin Stefanutti <anto...@stefanutti.fr>
Authored: Mon Apr 25 11:43:01 2016 +0200
Committer: Antonin Stefanutti <anto...@stefanutti.fr>
Committed: Mon Apr 25 11:43:01 2016 +0200

----------------------------------------------------------------------
 .../org/apache/camel/cdi/CdiCamelExtension.java | 122 +++++++++++++++----
 .../main/java/org/apache/camel/cdi/Main.java    |   9 +-
 .../camel/cdi/test/NamedCamelBeanTest.java      |  24 ++--
 .../camel/cdi/test/NoCamelContextTest.java      |  59 +++++++++
 4 files changed, 168 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b340d699/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
 
b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
index 19e3eba..dcb1e07 100755
--- 
a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
+++ 
b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
@@ -28,6 +28,8 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.Collections.addAll;
 import static java.util.Collections.newSetFromMap;
 import javax.enterprise.event.Observes;
 import javax.enterprise.inject.Default;
@@ -35,6 +37,7 @@ import javax.enterprise.inject.InjectionException;
 import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.spi.AfterBeanDiscovery;
 import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.Annotated;
 import javax.enterprise.inject.spi.AnnotatedMethod;
 import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.Bean;
@@ -54,6 +57,7 @@ import javax.inject.Named;
 import org.apache.camel.BeanInject;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
+import org.apache.camel.Component;
 import org.apache.camel.Consume;
 import org.apache.camel.ConsumerTemplate;
 import org.apache.camel.Converter;
@@ -69,6 +73,8 @@ import org.apache.camel.model.RouteContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.cdi.CdiSpiHelper.getFirstElementOfType;
+import static org.apache.camel.cdi.CdiSpiHelper.getRawType;
 import static org.apache.camel.cdi.CdiSpiHelper.hasAnnotation;
 
 public class CdiCamelExtension implements Extension {
@@ -85,6 +91,8 @@ public class CdiCamelExtension implements Extension {
 
     private final Map<InjectionPoint, ForwardingObserverMethod<?>> 
cdiEventEndpoints = new ConcurrentHashMap<>();
 
+    private final Set<Bean<?>> cdiBeans = newSetFromMap(new 
ConcurrentHashMap<Bean<?>, Boolean>());
+
     private final Set<Annotation> contextQualifiers = newSetFromMap(new 
ConcurrentHashMap<Annotation, Boolean>());
 
     private final Set<Annotation> eventQualifiers = newSetFromMap(new 
ConcurrentHashMap<Annotation, Boolean>());
@@ -93,8 +101,6 @@ public class CdiCamelExtension implements Extension {
 
     private final Map<Method, Set<Annotation>> producerQualifiers = new 
ConcurrentHashMap<>();
 
-    private final Set<ContextName> contextNames = newSetFromMap(new 
ConcurrentHashMap<ContextName, Boolean>());
-
     ForwardingObserverMethod<?> getObserverMethod(InjectionPoint ip) {
         return cdiEventEndpoints.get(ip);
     }
@@ -122,10 +128,6 @@ public class CdiCamelExtension implements Extension {
         }
     }
 
-    private void camelContextAware(@Observes ProcessAnnotatedType<? extends 
CamelContextAware> pat) {
-        camelBeans.add(pat.getAnnotatedType());
-    }
-
     private <T extends CamelContext> void camelContextBeans(@Observes 
ProcessInjectionTarget<T> pit, BeanManager manager) {
         
pit.setInjectionTarget(environment.camelContextInjectionTarget(pit.getInjectionTarget(),
 pit.getAnnotatedType(), manager, this));
     }
@@ -140,6 +142,10 @@ public class CdiCamelExtension implements Extension {
         }
     }
 
+    private <T extends CamelContextAware> void camelContextAware(@Observes 
ProcessInjectionTarget<T> pit, BeanManager manager) {
+        pit.setInjectionTarget(new 
CamelBeanInjectionTarget<>(pit.getInjectionTarget(), manager));
+    }
+
     private void cdiEventEndpoints(@Observes ProcessBean<?> pb) {
         for (InjectionPoint ip : pb.getBean().getInjectionPoints()) {
             if 
(!CdiEventEndpoint.class.equals(CdiSpiHelper.getRawType(ip.getType()))) {
@@ -197,43 +203,49 @@ public class CdiCamelExtension implements Extension {
         }
     }
 
-    private <T extends RoutesBuilder> void routeBuilderBeans(@Observes 
ProcessBean<T> pb) {
-        if (pb.getAnnotated().isAnnotationPresent(ContextName.class)) {
-            
contextNames.add(pb.getAnnotated().getAnnotation(ContextName.class));
-        }
-    }
-
-    private <T extends CamelContext> void camelContextBeans(@Observes 
ProcessBean<T> pb) {
-        contextQualifiers.addAll(pb.getBean().getQualifiers());
+    private void beans(@Observes ProcessProducerField<?, ?> pb) {
+        cdiBeans.add(pb.getBean());
     }
 
-    private <T extends CamelContext> void camelContextProducerFields(@Observes 
ProcessProducerField<T, ?> pb) {
-        contextQualifiers.addAll(pb.getBean().getQualifiers());
+    private void beans(@Observes ProcessProducerMethod<?, ?> pb) {
+        cdiBeans.add(pb.getBean());
     }
 
-    private <T extends CamelContext> void 
camelContextProducerMethods(@Observes ProcessProducerMethod<T, ?> pb) {
-        contextQualifiers.addAll(pb.getBean().getQualifiers());
+    private void beans(@Observes ProcessBean<?> pb) {
+        cdiBeans.add(pb.getBean());
     }
 
     private void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, 
BeanManager manager) {
-        // Missing @ContextName Camel context qualifiers
+        Set<ContextName> contextNames = new HashSet<>();
+        for (Bean<?> bean : cdiBeans) {
+            if (bean.getTypes().contains(CamelContext.class)) {
+                contextQualifiers.addAll(bean.getQualifiers());
+            } else if (bean.getTypes().contains(RoutesBuilder.class)
+                || bean.getTypes().contains(RouteContainer.class)) {
+                ContextName name = getFirstElementOfType(bean.getQualifiers(), 
ContextName.class);
+                if (name != null) {
+                    contextNames.add(name);
+                }
+            }
+        }
         contextNames.removeAll(contextQualifiers);
-        if (contextQualifiers.isEmpty() && contextNames.isEmpty()) {
+
+        if (contextQualifiers.isEmpty() && contextNames.isEmpty() && 
shouldDeployDefaultCamelContext(cdiBeans)) {
             // Add a @Default Camel context bean if any
             abd.addBean(camelContextBean(manager, AnyLiteral.INSTANCE, 
DefaultLiteral.INSTANCE));
         } else if (contextQualifiers.isEmpty() && contextNames.size() == 1) {
             // Add a @ContextName and @Default Camel context bean if only one
-            abd.addBean(camelContextBean(manager, AnyLiteral.INSTANCE, 
DefaultLiteral.INSTANCE, contextNames.iterator().next()));
+            ContextName name = contextNames.iterator().next();
+            abd.addBean(camelContextBean(manager, AnyLiteral.INSTANCE, 
DefaultLiteral.INSTANCE, name));
+            addAll(contextQualifiers, AnyLiteral.INSTANCE, 
DefaultLiteral.INSTANCE, name);
         } else {
             // Add missing @ContextName Camel context beans
             for (ContextName name : contextNames) {
                 abd.addBean(camelContextBean(manager, AnyLiteral.INSTANCE, 
name));
+                addAll(contextQualifiers, AnyLiteral.INSTANCE, name);
             }
         }
 
-        // Update @ContextName Camel context qualifiers
-        contextQualifiers.addAll(contextNames);
-
         // Then update the Camel producer beans
         for (Map.Entry<Method, Bean<?>> producer : producerBeans.entrySet()) {
             Bean<?> bean = producer.getValue();
@@ -260,6 +272,64 @@ public class CdiCamelExtension implements Extension {
         }
     }
 
+    private boolean shouldDeployDefaultCamelContext(Set<Bean<?>> beans) {
+        // Is there a Camel bean with the @Default qualifier?
+        for (Bean<?> bean : beans) {
+            if 
(bean.getBeanClass().getPackage().equals(getClass().getPackage())) {
+                continue;
+            }
+            if (bean.getTypes().contains(CamelContextAware.class)
+                || bean.getTypes().contains(Component.class)
+                || bean.getTypes().contains(RouteContainer.class)
+                || bean.getTypes().contains(RoutesBuilder.class)) {
+                if (bean.getQualifiers().contains(DefaultLiteral.INSTANCE)) {
+                    return true;
+                }
+            }
+        }
+        // Or a bean with Camel annotations?
+        for (AnnotatedType<?> type : camelBeans) {
+            for (Annotated field : type.getFields()) {
+                if (field.isAnnotationPresent(Consume.class) && 
field.getAnnotation(Consume.class).context().isEmpty()
+                    || field.isAnnotationPresent(BeanInject.class) && 
field.getAnnotation(BeanInject.class).context().isEmpty()
+                    || field.isAnnotationPresent(EndpointInject.class) && 
field.getAnnotation(EndpointInject.class).context().isEmpty()
+                    || field.isAnnotationPresent(Produce.class) && 
field.getAnnotation(Produce.class).context().isEmpty()
+                    || field.isAnnotationPresent(PropertyInject.class) && 
field.getAnnotation(PropertyInject.class).context().isEmpty()) {
+                    return true;
+                }
+            }
+            for (Annotated method : type.getMethods()) {
+                if (method.isAnnotationPresent(Consume.class) && 
method.getAnnotation(Consume.class).context().isEmpty()
+                    || method.isAnnotationPresent(BeanInject.class) && 
method.getAnnotation(BeanInject.class).context().isEmpty()
+                    || method.isAnnotationPresent(EndpointInject.class) && 
method.getAnnotation(EndpointInject.class).context().isEmpty()
+                    || method.isAnnotationPresent(Produce.class) && 
method.getAnnotation(Produce.class).context().isEmpty()
+                    || method.isAnnotationPresent(PropertyInject.class) && 
method.getAnnotation(PropertyInject.class).context().isEmpty()) {
+                    return true;
+                }
+            }
+        }
+        // Or an injection point for Camel primitives?
+        for (Bean<?> bean : beans) {
+            if 
(bean.getBeanClass().getPackage().equals(getClass().getPackage())) {
+                continue;
+            }
+            for (InjectionPoint ip : bean.getInjectionPoints()) {
+                if 
(!getRawType(ip.getType()).getPackage().getName().startsWith("org.apache.camel"))
 {
+                    continue;
+                }
+                for (Annotation qualifier : ip.getQualifiers()) {
+                    if (qualifier.annotationType().equals(Uri.class)
+                        || qualifier.annotationType().equals(Mock.class)
+                        || qualifier.annotationType().equals(Default.class)) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
     private Bean<?> camelContextBean(BeanManager manager, Annotation... 
qualifiers) {
         CdiCamelContextAnnotated annotated = new 
CdiCamelContextAnnotated(manager, qualifiers);
         return new CdiCamelContextBean(annotated, 
environment.camelContextInjectionTarget(new CamelContextDefaultProducer(), 
annotated, manager, this));
@@ -317,12 +387,12 @@ public class CdiCamelExtension implements Extension {
         }
 
         // Clean-up
-        converters.clear();
         camelBeans.clear();
+        cdiBeans.clear();
+        converters.clear();
         eagerBeans.clear();
         producerBeans.clear();
         producerQualifiers.clear();
-        contextNames.clear();
     }
 
     private boolean addRouteToContext(Bean<?> routeBean, Bean<?> contextBean, 
BeanManager manager, AfterDeploymentValidation adv) {

http://git-wip-us.apache.org/repos/asf/camel/blob/b340d699/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java 
b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
index ebdae5b..4700959 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
@@ -102,11 +102,10 @@ public class Main extends MainSupport {
 
     private void warnIfNoCamelFound() {
         BeanManager manager = cdiContainer.getBeanManager();
-        Set<Bean<?>> contexts = manager.getBeans(CamelContext.class);
-        // Warn if the default CDI Camel context has no routes
-        if (contexts.size() == 1 && BeanManagerHelper.getReference(manager, 
CamelContext.class, contexts.iterator().next()).getRoutes().isEmpty()) {
-            LOG.warn("Camel CDI main has started with no Camel routes! "
-                   + "You may add some RouteBuilder beans to your project.");
+        Set<Bean<?>> contexts = manager.getBeans(CamelContext.class, 
AnyLiteral.INSTANCE);
+        // Warn if there is no CDI Camel contexts
+        if (contexts.isEmpty()) {
+            LOG.warn("Camel CDI main has started with no Camel context!");
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b340d699/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NamedCamelBeanTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NamedCamelBeanTest.java
 
b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NamedCamelBeanTest.java
index cb93c55..fbb2879 100644
--- 
a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NamedCamelBeanTest.java
+++ 
b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NamedCamelBeanTest.java
@@ -18,7 +18,6 @@ package org.apache.camel.cdi.test;
 
 import java.util.concurrent.TimeUnit;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.cdi.CdiCamelExtension;
@@ -27,7 +26,6 @@ import org.apache.camel.cdi.bean.NamedCamelBean;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
-import org.jboss.arquillian.junit.InSequence;
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.EmptyAsset;
@@ -52,19 +50,8 @@ public class NamedCamelBeanTest {
     }
 
     @Test
-    @InSequence(1)
-    public void configureCamelContext(CamelContext context) throws Exception {
-        context.addRoutes(new RouteBuilder() {
-            @Override
-            public void configure() {
-                from("direct:inbound").bean("beanName").to("mock:outbound");
-            }
-        });
-    }
-
-    @Test
-    @InSequence(2)
-    public void sendMessageToInbound(@Uri("direct:inbound") ProducerTemplate 
in, @Uri("mock:outbound") MockEndpoint out) throws InterruptedException {
+    public void sendMessageToInbound(@Uri("direct:inbound") ProducerTemplate 
in,
+                                     @Uri("mock:outbound") MockEndpoint out) 
throws InterruptedException {
         out.expectedMessageCount(1);
         out.expectedBodiesReceived("test-processed");
         
@@ -72,4 +59,11 @@ public class NamedCamelBeanTest {
 
         assertIsSatisfied(2L, TimeUnit.SECONDS, out);
     }
+
+    private static class TestRoute extends RouteBuilder {
+        @Override
+        public void configure() {
+            from("direct:inbound").bean("beanName").to("mock:outbound");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b340d699/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NoCamelContextTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NoCamelContextTest.java
 
b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NoCamelContextTest.java
new file mode 100644
index 0000000..c1d85ad
--- /dev/null
+++ 
b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/NoCamelContextTest.java
@@ -0,0 +1,59 @@
+/**
+ * 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.cdi.test;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cdi.CdiCamelExtension;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+
+@RunWith(Arquillian.class)
+public class NoCamelContextTest {
+
+    @Any
+    @Inject
+    private Instance<CamelContext> contexts;
+
+    @Deployment
+    public static Archive<?> deployment() {
+        return ShrinkWrap.create(JavaArchive.class)
+            // Camel CDI
+            .addPackage(CdiCamelExtension.class.getPackage())
+            // Bean archive deployment descriptor
+            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+    }
+
+    @Test
+    public void verifyDeployment() {
+        assertThat("Camel context beans are deployed!", 
contexts.isUnsatisfied(), is(equalTo(true)));
+    }
+}

Reply via email to