You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/01/15 14:44:16 UTC

[8/9] camel git commit: CAMEL-9201: Improved Camel CDI component

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
new file mode 100644
index 0000000..4b14b9d
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
@@ -0,0 +1,45 @@
+/**
+ * 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;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.impl.DefaultCamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextNameStrategy;
+
+/**
+ * A {@link CamelContextNameStrategy} for Camel contexts that are managed by Camel CDI.
+ *
+ * As opposed to {@link org.apache.camel.impl.DefaultCamelContextNameStrategy},
+ * this implementation does not increment the suffix for proxies that are created
+ * each time a contextual reference to a normal-scoped bean is retrieved.
+ *
+ * It is used by Camel CDI for custom Camel context beans that do not override
+ * the context name nor the naming strategy.
+ *
+ * @see CamelContextNameStrategy
+ */
+@Vetoed
+final class CdiCamelContextNameStrategy extends DefaultCamelContextNameStrategy implements CamelContextNameStrategy {
+
+    private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger(0);
+
+    @Override
+    public String getNextName() {
+        return "camel" + "-" + CONTEXT_COUNTER.incrementAndGet();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
new file mode 100644
index 0000000..b5cbf58
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
@@ -0,0 +1,66 @@
+/**
+ * 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;
+
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Producer;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.core.osgi.utils.BundleContextUtils;
+
+@Vetoed
+final class CdiCamelEnvironment {
+
+    private final boolean hasBundleContext;
+
+    CdiCamelEnvironment() {
+        hasBundleContext = isCamelCoreOsgiPresent() && hasBundleContext(CdiCamelExtension.class);
+    }
+
+    <T extends CamelContext> Producer<T> camelContextProducer(Producer<T> delegate, Annotated annotated, BeanManager manager, CdiCamelExtension extension) {
+        CamelContextProducer<T> producer = new CamelContextProducer<>(delegate, annotated, manager, extension);
+        return hasBundleContext ? new CamelContextOsgiProducer<>(producer) : producer;
+    }
+
+    <T extends CamelContext> InjectionTarget<T> camelContextInjectionTarget(InjectionTarget<T> delegate, Annotated annotated, BeanManager manager, CdiCamelExtension extension) {
+        CamelContextProducer<T> producer = new CamelContextProducer<>(delegate, annotated, manager, extension);
+        return new CamelContextInjectionTarget<>(delegate, hasBundleContext ? new CamelContextOsgiProducer<>(producer) : producer);
+    }
+
+    private static boolean isCamelCoreOsgiPresent() {
+        try {
+            getClassLoader(CdiCamelExtension.class).loadClass("org.apache.camel.core.osgi.OsgiCamelContextHelper");
+            return true;
+        } catch (ClassNotFoundException cause) {
+            return false;
+        }
+    }
+
+    private static boolean hasBundleContext(Class clazz) {
+        return BundleContextUtils.getBundleContext(clazz) != null;
+    }
+
+    private static ClassLoader getClassLoader(Class<?> clazz) {
+        if (Thread.currentThread().getContextClassLoader() != null) {
+            return Thread.currentThread().getContextClassLoader();
+        } else {
+            return clazz.getClassLoader();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/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
new file mode 100755
index 0000000..6951cc3
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
@@ -0,0 +1,328 @@
+/**
+ * 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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import static java.util.Collections.newSetFromMap;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+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;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.ObserverMethod;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessBean;
+import javax.enterprise.inject.spi.ProcessInjectionTarget;
+import javax.enterprise.inject.spi.ProcessObserverMethod;
+import javax.enterprise.inject.spi.ProcessProducer;
+import javax.enterprise.inject.spi.ProcessProducerField;
+import javax.enterprise.inject.spi.ProcessProducerMethod;
+import javax.inject.Named;
+
+import org.apache.camel.BeanInject;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Consume;
+import org.apache.camel.Converter;
+import org.apache.camel.Endpoint;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.PropertyInject;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.management.event.AbstractExchangeEvent;
+import org.apache.camel.model.RouteContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.camel.cdi.CdiSpiHelper.hasAnnotation;
+
+public class CdiCamelExtension implements Extension {
+
+    private final Logger logger = LoggerFactory.getLogger(CdiCamelExtension.class);
+
+    private final CdiCamelEnvironment environment = new CdiCamelEnvironment();
+
+    private final Set<Class<?>> converters = newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());
+
+    private final Set<AnnotatedType<?>> camelBeans = newSetFromMap(new ConcurrentHashMap<AnnotatedType<?>, Boolean>());
+
+    private final Set<AnnotatedType<?>> eagerBeans = newSetFromMap(new ConcurrentHashMap<AnnotatedType<?>, Boolean>());
+
+    private final Map<InjectionPoint, ForwardingObserverMethod<?>> cdiEventEndpoints = new ConcurrentHashMap<>();
+
+    private final Map<Annotated, Bean<?>> contextBeans = new ConcurrentHashMap<>();
+
+    private final Set<Annotation> contextQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
+
+    private final Set<Annotation> eventQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
+
+    private final Map<Method, Bean<?>> producerBeans = new ConcurrentHashMap<>();
+
+    private final Map<Method, Set<Annotation>> producerQualifiers = new ConcurrentHashMap<>();
+
+    ForwardingObserverMethod<?> getObserverMethod(InjectionPoint ip) {
+        return cdiEventEndpoints.get(ip);
+    }
+
+    Set<Annotation> getObserverEvents() {
+        return eventQualifiers;
+    }
+
+    Bean<?> getContextBean(Annotated annotated) {
+        return contextBeans.get(annotated);
+    }
+
+    Set<Annotation> getContextQualifiers() {
+        return contextQualifiers;
+    }
+
+    private void processAnnotatedType(@Observes ProcessAnnotatedType<?> pat) {
+        if (pat.getAnnotatedType().isAnnotationPresent(Vetoed.class)) {
+            pat.veto();
+        }
+        if (hasAnnotation(pat.getAnnotatedType(), Converter.class)) {
+            converters.add(pat.getAnnotatedType().getJavaClass());
+        }
+        if (hasAnnotation(pat.getAnnotatedType(), BeanInject.class, Consume.class, EndpointInject.class, Produce.class, PropertyInject.class)) {
+            camelBeans.add(pat.getAnnotatedType());
+        }
+        if (hasAnnotation(pat.getAnnotatedType(), Consume.class)) {
+            eagerBeans.add(pat.getAnnotatedType());
+        }
+    }
+
+    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));
+    }
+
+    private <T extends CamelContext> void camelContextProducers(@Observes ProcessProducer<?, T> pp, BeanManager manager) {
+        pp.setProducer(environment.camelContextProducer(pp.getProducer(), pp.getAnnotatedMember(), manager, this));
+    }
+
+    private <T> void camelBeansPostProcessor(@Observes ProcessInjectionTarget<T> pit, BeanManager manager) {
+        if (camelBeans.contains(pit.getAnnotatedType())) {
+            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()))) {
+                continue;
+            }
+            // TODO: refine the key to the type and qualifiers instead of the whole injection point as it leads to registering redundant observers
+            if (ip.getType() instanceof ParameterizedType) {
+                cdiEventEndpoints.put(ip, new ForwardingObserverMethod<>(((ParameterizedType) ip.getType()).getActualTypeArguments()[0], ip.getQualifiers()));
+            } else if (ip.getType() instanceof Class) {
+                cdiEventEndpoints.put(ip, new ForwardingObserverMethod<>(Object.class, ip.getQualifiers()));
+            }
+        }
+    }
+
+    private <T extends Endpoint> void endpointBeans(@Observes ProcessProducerMethod<T, CdiCamelFactory> ppm) {
+        producerBeans.put(ppm.getAnnotatedProducerMethod().getJavaMember(), ppm.getBean());
+    }
+
+    private void producerTemplateBeans(@Observes ProcessProducerMethod<ProducerTemplate, CdiCamelFactory> ppm) {
+        producerBeans.put(ppm.getAnnotatedProducerMethod().getJavaMember(), ppm.getBean());
+    }
+
+    private void camelFactoryProducers(@Observes ProcessAnnotatedType<CdiCamelFactory> pat, BeanManager manager) {
+        AnnotatedType<CdiCamelFactory> at = pat.getAnnotatedType();
+        Set<AnnotatedMethod<? super CdiCamelFactory>> methods = new HashSet<>();
+        for (AnnotatedMethod<? super CdiCamelFactory> am : pat.getAnnotatedType().getMethods()) {
+            if (!am.isAnnotationPresent(Produces.class)) {
+                continue;
+            }
+            Class<?> type = CdiSpiHelper.getRawType(am.getBaseType());
+            if (Endpoint.class.isAssignableFrom(type) || ProducerTemplate.class.equals(type)) {
+                Set<Annotation> qualifiers = CdiSpiHelper.getQualifiers(am, manager);
+                producerQualifiers.put(am.getJavaMember(), qualifiers.isEmpty() ? Collections.<Annotation>singleton(DefaultLiteral.INSTANCE) : qualifiers);
+                Set<Annotation> annotations = new HashSet<>(am.getAnnotations());
+                annotations.removeAll(qualifiers);
+                annotations.add(Excluded.INSTANCE);
+                methods.add(new AnnotatedMethodDelegate<>(am, annotations));
+            }
+        }
+        pat.setAnnotatedType(new AnnotatedTypeDelegate<>(at, methods));
+    }
+
+    private <T extends EventObject> void camelEventNotifiers(@Observes ProcessObserverMethod<T, ?> pom) {
+        // Only activate Camel event notifiers for explicit Camel event observers, that is, an observer method for a super type won't activate notifiers.
+        Type type = pom.getObserverMethod().getObservedType();
+        // Camel events are raw types
+        if (type instanceof Class && Class.class.cast(type).getPackage().equals(AbstractExchangeEvent.class.getPackage())) {
+            eventQualifiers.addAll(pom.getObserverMethod().getObservedQualifiers().isEmpty() ? Collections.singleton(AnyLiteral.INSTANCE) : pom.getObserverMethod().getObservedQualifiers());
+        }
+    }
+
+    private <T extends CamelContext> void camelContextBeans(@Observes ProcessBean<T> pb) {
+        processCamelContextBean(pb.getAnnotated(), pb.getBean());
+    }
+
+    private <T extends CamelContext> void camelContextProducerFields(@Observes ProcessProducerField<T, ?> pb) {
+        processCamelContextBean(pb.getAnnotated(), pb.getBean());
+    }
+
+    private <T extends CamelContext> void camelContextProducerMethods(@Observes ProcessProducerMethod<T, ?> pb) {
+        processCamelContextBean(pb.getAnnotated(), pb.getBean());
+    }
+
+    private void processCamelContextBean(Annotated annotated, Bean<?> bean) {
+        contextQualifiers.addAll(bean.getQualifiers());
+        // Annotated must be wrapped because of OWB-1099
+        contextBeans.put(new AnnotatedWrapper(annotated), bean);
+    }
+
+    private void cdiCamelFactoryProducers(@Observes AfterBeanDiscovery abd) {
+        for (Map.Entry<Method, Bean<?>> producer : producerBeans.entrySet()) {
+            Bean<?> bean = producer.getValue();
+            Set<Annotation> qualifiers = new HashSet<>(producerQualifiers.get(producer.getKey()));
+            Class<?> type = producer.getKey().getReturnType();
+            if (CdiEventEndpoint.class.equals(type)) {
+                for (InjectionPoint ip : cdiEventEndpoints.keySet()) {
+                    qualifiers.addAll(ip.getQualifiers());
+                }
+            } else {
+                if (Endpoint.class.isAssignableFrom(type) || ProducerTemplate.class.isAssignableFrom(type)) {
+                    qualifiers.addAll(CdiSpiHelper.excludeElementOfTypes(contextQualifiers, Any.class, Default.class, Named.class));
+                }
+            }
+            // TODO: would be more correct to add a bean for each Camel context bean
+            abd.addBean(new BeanDelegate<>(bean, qualifiers));
+        }
+    }
+
+    private void addDefaultCamelContext(@Observes AfterBeanDiscovery abd, BeanManager manager) {
+        if (contextBeans.isEmpty()) {
+            abd.addBean(new CdiCamelContextBean(manager, environment.camelContextInjectionTarget(new CamelContextDefaultProducer(), null, manager, CdiCamelExtension.this)));
+        }
+    }
+
+    private void addCdiEventObserverMethods(@Observes AfterBeanDiscovery abd) {
+        for (ObserverMethod method : cdiEventEndpoints.values()) {
+            abd.addObserverMethod(method);
+        }
+    }
+
+    private void createCamelContexts(@Observes AfterDeploymentValidation adv, BeanManager manager) {
+        Collection<CamelContext> contexts = new ArrayList<>();
+        for (Bean<?> context : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+            contexts.add(BeanManagerHelper.getReference(manager, CamelContext.class, context));
+        }
+
+        // Add type converters to Camel contexts
+        CdiTypeConverterLoader loader = new CdiTypeConverterLoader();
+        for (Class<?> converter : converters) {
+            for (CamelContext context : contexts) {
+                loader.loadConverterMethods(context.getTypeConverterRegistry(), converter);
+            }
+        }
+
+        // Add routes to Camel contexts
+        boolean deploymentException = false;
+        Set<Bean<?>> routes = new HashSet<>(manager.getBeans(RoutesBuilder.class, AnyLiteral.INSTANCE));
+        routes.addAll(manager.getBeans(RouteContainer.class, AnyLiteral.INSTANCE));
+        for (Bean<?> context : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+            for (Bean<?> route : routes) {
+                Set<Annotation> qualifiers = new HashSet<>(context.getQualifiers());
+                qualifiers.retainAll(route.getQualifiers());
+                if (qualifiers.size() > 1) {
+                    deploymentException |= !addRouteToContext(route, context, manager, adv);
+                }
+            }
+        }
+        // Let's return to avoid starting misconfigured contexts
+        if (deploymentException) {
+            return;
+        }
+
+        // Trigger eager beans instantiation
+        for (AnnotatedType<?> type : eagerBeans) {
+            // Calling toString is necessary to force the initialization of normal-scoped beans
+            BeanManagerHelper.getReferencesByType(manager, type.getJavaClass(), AnyLiteral.INSTANCE).toString();
+        }
+
+        // Start Camel contexts
+        for (CamelContext context : contexts) {
+            if (ServiceStatus.Started.equals(context.getStatus())) {
+                continue;
+            }
+            logger.info("Camel CDI is starting Camel context [{}]", context.getName());
+            try {
+                context.start();
+            } catch (Exception exception) {
+                adv.addDeploymentProblem(exception);
+            }
+        }
+
+        // Clean-up
+        converters.clear();
+        camelBeans.clear();
+        eagerBeans.clear();
+        producerBeans.clear();
+        producerQualifiers.clear();
+    }
+
+    private boolean addRouteToContext(Bean<?> routeBean, Bean<?> contextBean, BeanManager manager, AfterDeploymentValidation adv) {
+        try {
+            CamelContext context = BeanManagerHelper.getReference(manager, CamelContext.class, contextBean);
+            try {
+                Object route = BeanManagerHelper.getReference(manager, Object.class, routeBean);
+                if (route instanceof RoutesBuilder) {
+                    context.addRoutes((RoutesBuilder) route);
+                } else if (route instanceof RouteContainer) {
+                    context.addRouteDefinitions(((RouteContainer) route).getRoutes());
+                } else {
+                    throw new IllegalArgumentException("Invalid routes type [" + routeBean.getBeanClass().getName() + "], must be either of type RoutesBuilder or RouteContainer!");
+                }
+                return true;
+            } catch (Exception cause) {
+                adv.addDeploymentProblem(new InjectionException("Error adding routes of type [" + routeBean.getBeanClass().getName() + "] to Camel context [" + context.getName() + "]", cause));
+            }
+        } catch (Exception exception) {
+            adv.addDeploymentProblem(exception);
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
new file mode 100755
index 0000000..cdb2336
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
@@ -0,0 +1,211 @@
+/**
+ * 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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.enterprise.event.Event;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.TypeLiteral;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.mock.MockEndpoint;
+
+final class CdiCamelFactory {
+
+    @Produces
+    private static TypeConverter typeConverter(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        return selectContext(ip, instance, extension).getTypeConverter();
+    }
+
+    @Uri("")
+    @Produces
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static ProducerTemplate producerTemplate(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+        try {
+            CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+            ProducerTemplate producerTemplate = context.createProducerTemplate();
+            // FIXME: avoid NPE caused by missing @Uri qualifier when injection point is @ContextName qualified
+            Endpoint endpoint = context.getEndpoint(uri.value(), Endpoint.class);
+            producerTemplate.setDefaultEndpoint(endpoint);
+            return producerTemplate;
+        } catch (Exception cause) {
+            throw new InjectionException("Error injecting producer template annotated with " + uri + " into " + ip, cause);
+        }
+    }
+
+    @Produces
+    @Typed(MockEndpoint.class)
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static MockEndpoint mockEndpointFromMember(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        String uri = "mock:" + ip.getMember().getName();
+        try {
+            return selectContext(ip, instance, extension).getEndpoint(uri, MockEndpoint.class);
+        } catch (Exception cause) {
+            throw new InjectionException("Error injecting mock endpoint into " + ip, cause);
+        }
+    }
+
+    @Uri("")
+    @Produces
+    @Typed(MockEndpoint.class)
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static MockEndpoint mockEndpointFromUri(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+        try {
+            CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+            return context.getEndpoint(uri.value(), MockEndpoint.class);
+        } catch (Exception cause) {
+            throw new InjectionException("Error injecting mock endpoint annotated with " + uri
+                + " into " + ip, cause);
+        }
+    }
+
+    // Maintained for backward compatibility reason though this is redundant with @Uri
+    // see https://issues.apache.org/jira/browse/CAMEL-5553?focusedCommentId=13445936&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13445936
+    @Mock("")
+    @Produces
+    @Typed(MockEndpoint.class)
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static MockEndpoint createMockEndpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        Mock mock = CdiSpiHelper.getQualifierByType(ip, Mock.class);
+        try {
+            CamelContext context = mock.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(mock.context(), instance);
+            return context.getEndpoint(mock.value(), MockEndpoint.class);
+        } catch (Exception cause) {
+            throw new InjectionException("Error injecting mock endpoint annotated with " + mock + " into " + ip, cause);
+        }
+    }
+
+    @Uri("")
+    @Produces
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static Endpoint endpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+        Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+        try {
+            CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+            return context.getEndpoint(uri.value(), Endpoint.class);
+        } catch (Exception cause) {
+            throw new InjectionException("Error injecting endpoint annotated with " + uri + " into " + ip, cause);
+        }
+    }
+
+    @Produces
+    @SuppressWarnings("unchecked")
+    // Qualifiers are dynamically added in CdiCamelExtension
+    private static <T> CdiEventEndpoint<T> cdiEventEndpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension, @Any Event<Object> event) throws Exception {
+        CamelContext context = selectContext(ip, instance, extension);
+        Type type = Object.class;
+        if (ip.getType() instanceof ParameterizedType) {
+            type = ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
+        }
+        String uri = eventEndpointUri(type, ip.getQualifiers());
+        if (context.hasEndpoint(uri) == null) {
+            // FIXME: to be replaced once event firing with dynamic parameterized type is properly supported (see https://issues.jboss.org/browse/CDI-516)
+            TypeLiteral<T> literal = new TypeLiteral<T>() {
+            };
+            for (Field field : TypeLiteral.class.getDeclaredFields()) {
+                if (field.getType().equals(Type.class)) {
+                    field.setAccessible(true);
+                    field.set(literal, type);
+                    break;
+                }
+            }
+            context.addEndpoint(uri,
+                new CdiEventEndpoint<>(
+                    event.select(literal, ip.getQualifiers().toArray(new Annotation[ip.getQualifiers().size()])), uri, context, (ForwardingObserverMethod<T>) extension.getObserverMethod(ip)));
+        }
+        return context.getEndpoint(uri, CdiEventEndpoint.class);
+    }
+
+    private static <T extends CamelContext> T selectContext(String name, Instance<T> instance) {
+        for (T context : instance) {
+            if (name.equals(context.getName())) {
+                return context;
+            }
+        }
+        throw new UnsatisfiedResolutionException("No Camel context with name [" + name + "] is deployed!");
+    }
+
+    private static <T extends CamelContext> T selectContext(InjectionPoint ip, Instance<T> instance, CdiCamelExtension extension) {
+        Collection<Annotation> qualifiers = new HashSet<>(ip.getQualifiers());
+        qualifiers.retainAll(extension.getContextQualifiers());
+        if (qualifiers.isEmpty() && !instance.select(DefaultLiteral.INSTANCE).isUnsatisfied()) {
+            return instance.select(DefaultLiteral.INSTANCE).get();
+        }
+        return instance.select(qualifiers.toArray(new Annotation[qualifiers.size()])).get();
+    }
+
+    private static String eventEndpointUri(Type type, Set<Annotation> qualifiers) {
+        String uri = "cdi-event://" + authorityFromType(type);
+        StringBuilder parameters = new StringBuilder();
+        Iterator<Annotation> it = qualifiers.iterator();
+        while (it.hasNext()) {
+            parameters.append(it.next().annotationType().getCanonicalName());
+            if (it.hasNext()) {
+                parameters.append("%2C");
+            }
+        }
+        if (parameters.length() > 0) {
+            uri += "?qualifiers=" + parameters.toString();
+        }
+        return uri;
+    }
+
+    private static String authorityFromType(Type type) {
+        if (type instanceof Class) {
+            return Class.class.cast(type).getName();
+        }
+        if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) type;
+            StringBuilder builder = new StringBuilder(authorityFromType(pt.getRawType()));
+            Iterator<Type> it = Arrays.asList(pt.getActualTypeArguments()).iterator();
+            builder.append("%3C");
+            while (it.hasNext()) {
+                builder.append(authorityFromType(it.next()));
+                if (it.hasNext()) {
+                    builder.append("%2C");
+                }
+            }
+            builder.append("%3E");
+            return builder.toString();
+        }
+        if (type instanceof GenericArrayType) {
+            GenericArrayType arrayType = (GenericArrayType) type;
+            return authorityFromType(arrayType.getGenericComponentType()) + "%5B%5D";
+        }
+        throw new IllegalArgumentException("Cannot create URI authority for event type [" + type + "]");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
new file mode 100755
index 0000000..471b7f0
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
@@ -0,0 +1,48 @@
+/**
+ * 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;
+
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.spi.Injector;
+
+final class CdiCamelInjector implements Injector {
+
+    private final Injector injector;
+
+    private final BeanManager manager;
+
+    CdiCamelInjector(Injector injector, BeanManager manager) {
+        this.injector = injector;
+        this.manager = manager;
+    }
+
+    @Override
+    public <T> T newInstance(Class<T> type) {
+        T instance = BeanManagerHelper.getReferenceByType(manager, type);
+        if (instance != null) {
+            return instance;
+        } else {
+            return injector.newInstance(type);
+        }
+    }
+
+    @Override
+    public <T> T newInstance(Class<T> type, Object instance) {
+        return injector.newInstance(type, instance);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
new file mode 100755
index 0000000..946fecf
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
@@ -0,0 +1,98 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link Registry} used by Camel to perform lookup into the CDI {@link BeanManager}.
+ */
+@Vetoed
+final class CdiCamelRegistry implements Registry {
+
+    private final Logger logger = LoggerFactory.getLogger(CdiCamelRegistry.class);
+
+    private final BeanManager manager;
+
+    CdiCamelRegistry(BeanManager manager) {
+        this.manager = manager;
+    }
+
+    @Override
+    public Object lookupByName(String name) {
+        ObjectHelper.notEmpty(name, "name");
+        logger.trace("Looking up bean with name [{}]", name);
+        // Work-around for WELD-2089
+        if ("properties".equals(name) && findByTypeWithName(PropertiesComponent.class).containsKey("properties")) {
+            return BeanManagerHelper.getReferenceByName(manager, name, PropertiesComponent.class);
+        }
+        return BeanManagerHelper.getReferenceByName(manager, name, Object.class);
+    }
+
+    @Override
+    public <T> T lookupByNameAndType(String name, Class<T> type) {
+        ObjectHelper.notEmpty(name, "name");
+        ObjectHelper.notNull(type, "type");
+        logger.trace("Looking up bean with name [{}] of type [{}]", name, type);
+        return BeanManagerHelper.getReferenceByName(manager, name, type);
+    }
+
+    @Override
+    public <T> Map<String, T> findByTypeWithName(Class<T> type) {
+        ObjectHelper.notNull(type, "type");
+        logger.trace("Looking up named beans of type [{}]", type);
+        Map<String, T> references = new HashMap<>();
+        for (Bean<?> bean : manager.getBeans(type, AnyLiteral.INSTANCE)) {
+            if (bean.getName() != null) {
+                references.put(bean.getName(), BeanManagerHelper.getReference(manager, type, bean));
+            }
+        }
+        return references;
+    }
+
+    @Override
+    public <T> Set<T> findByType(Class<T> type) {
+        ObjectHelper.notNull(type, "type");
+        logger.trace("Looking up beans of type [{}]", type);
+        return BeanManagerHelper.getReferencesByType(manager, type, AnyLiteral.INSTANCE);
+    }
+
+    @Override
+    public Object lookup(String name) {
+        return lookupByName(name);
+    }
+
+    @Override
+    public <T> T lookup(String name, Class<T> type) {
+        return lookupByNameAndType(name, type);
+    }
+
+    @Override
+    public <T> Map<String, T> lookupByType(Class<T> type) {
+        return findByTypeWithName(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
new file mode 100644
index 0000000..ffc4d89
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
@@ -0,0 +1,53 @@
+/**
+ * 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;
+
+import java.util.Map;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.impl.DefaultComponent;
+
+@Named("cdi-event")
+@ApplicationScoped
+/* package-private */ class CdiEventComponent extends DefaultComponent {
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) {
+        /* The CDI event endpoint URI follows the format hereafter:
+        
+        cdi-event://PayloadType<T1,...,Tn>[?qualifiers=QualifierType1[,...[,QualifierTypeN]...]]
+
+        with the authority PayloadType (respectively the QualifierType) being the URI escaped fully
+        qualified name of the payload (respectively qualifier) raw type followed by the type parameters
+        section delimited by angle brackets for payload parameterized type.
+
+        Which leads to unfriendly URIs, e.g.:
+
+        cdi-event://org.apache.camel.cdi.se.pojo.EventPayload%3Cjava.lang.Integer%3E?qualifiers=org.apache.camel.cdi.se.qualifier.FooQualifier%2Corg.apache.camel.cdi.se.qualifier.BarQualifier
+
+        From the conceptual standpoint, that shows the high impedance between the typesafe nature of CDI
+        and the dynamic nature of the Camel component model.
+
+        From the implementation standpoint, that would prevent efficient binding between the endpoint
+        instances and observer methods as the CDI container doesn't have any ways of discovering the
+        Camel context model during the deployment phase.
+        */
+        throw new UnsupportedOperationException("Creating CDI event endpoint isn't supported. Use @Inject " + CdiEventEndpoint.class.getSimpleName() + " instead");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
new file mode 100644
index 0000000..f479163
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
@@ -0,0 +1,71 @@
+/**
+ * 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;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeExchangeException;
+import org.apache.camel.impl.DefaultConsumer;
+import org.apache.camel.management.event.AbstractExchangeEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* package-private */ final class CdiEventConsumer<T> extends DefaultConsumer {
+
+    private final Logger logger = LoggerFactory.getLogger(CdiEventConsumer.class);
+
+    private final CdiEventEndpoint<T> endpoint;
+
+    CdiEventConsumer(CdiEventEndpoint<T> endpoint, Processor processor) {
+        super(endpoint, processor);
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        endpoint.registerConsumer(this);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        endpoint.unregisterConsumer(this);
+        super.doStop();
+    }
+
+    void notify(T event) {
+        logger.debug("Consuming CDI event [{}] with {}", event, this);
+
+        Exchange exchange = getEndpoint().createExchange();
+        // TODO: would that be possible to propagate the event metadata?
+        exchange.getIn().setBody(event);
+
+        // Avoid infinite loop of exchange events
+        if (event instanceof AbstractExchangeEvent) {
+            exchange.setProperty(Exchange.NOTIFY_EVENT, Boolean.TRUE);
+        }
+        try {
+            getProcessor().process(exchange);
+        } catch (Exception cause) {
+            throw new RuntimeExchangeException("Error while processing CDI event", exchange, cause);
+        } finally {
+            if (event instanceof AbstractExchangeEvent) {
+                exchange.setProperty(Exchange.NOTIFY_EVENT, Boolean.FALSE);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
new file mode 100644
index 0000000..a003609
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
@@ -0,0 +1,127 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.enterprise.event.Event;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+
+/**
+ * A Camel {@link Endpoint} that bridges the CDI events facility with Camel routes so that CDI events
+ * can be seamlessly observed / consumed (respectively produced / fired) from Camel consumers (respectively by Camel producers).
+ * <p/>
+ * The {@code CdiEventEndpoint<T>} bean can be used to observe / consume CDI events whose event type is {@code T}, for example:
+ * <pre><code>
+ * {@literal @}Inject
+ * CdiEventEndpoint{@literal <}String{@literal >} cdiEventEndpoint;
+ *
+ * from(cdiEventEndpoint).log("CDI event received: ${body}");
+ * </code></pre>
+ *
+ * Conversely, the {@code CdiEventEndpoint<T>} bean can be used to produce / fire CDI events whose event type is {@code T}, for example:
+ * <pre><code>
+ * {@literal @}Inject
+ * CdiEventEndpoint{@literal <}String{@literal >} cdiEventEndpoint;
+ *
+ * from("direct:event").to(cdiEventEndpoint).log("CDI event sent: ${body}");
+ * </code></pre>
+ *
+ * The type variable {@code T}, respectively the qualifiers, of a particular {@code CdiEventEndpoint<T>} injection point
+ * are automatically translated into the parameterized <i>event type</i>, respectively into the <i>event qualifiers</i>, e.g.:
+ * <pre><code>
+ * {@literal @}Inject
+ * {@literal @}FooQualifier
+ * CdiEventEndpoint{@literal <}List{@literal <}String{@literal >}{@literal >} cdiEventEndpoint;
+ *
+ * from("direct:event").to(cdiEventEndpoint);
+ *
+ * void observeCdiEvents({@literal @}Observes {@literal @}FooQualifier List{@literal <}String{@literal >} event) {
+ *     logger.info("CDI event: {}", event);
+ * }
+ * </code></pre>
+ *
+ * When multiple Camel contexts exist in the CDI container, the {@code @ContextName} qualifier can be used
+ * to qualify the {@code CdiEventEndpoint<T>} injection points, e.g.:
+ * <pre><code>
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * CdiEventEndpoint{@literal <}List{@literal <}String{@literal >}{@literal >} cdiEventEndpoint;
+ *
+ * // Only observe / consume events having the {@literal @}ContextName("foo") qualifier
+ * from(cdiEventEndpoint).log("Camel context 'foo' > CDI event received: ${body}");
+ *
+ * // Produce / fire events with the {@literal @}ContextName("foo") qualifier
+ * from("...").to(cdiEventEndpoint);
+ *
+ * void observeCdiEvents({@literal @}Observes {@literal @}ContextName("foo") List{@literal <}String{@literal >} event) {
+ *     logger.info("Camel context 'foo' > CDI event: {}", event);
+ * }
+ * </code></pre>
+ */
+public final class CdiEventEndpoint<T> extends DefaultEndpoint {
+
+    private final List<CdiEventConsumer<T>> consumers = new ArrayList<>();
+
+    private final Event<T> event;
+
+    CdiEventEndpoint(Event<T> event, String endpointUri, CamelContext context, ForwardingObserverMethod<T> observer) {
+        super(endpointUri, context);
+        this.event = event;
+        observer.setObserver(this);
+    }
+
+    public Consumer createConsumer(Processor processor) {
+        return new CdiEventConsumer<>(this, processor);
+    }
+
+    @Override
+    public Producer createProducer() {
+        return new CdiEventProducer<>(this, event);
+    }
+
+    @Override
+    public boolean isSingleton() {
+        return true;
+    }
+
+    void registerConsumer(CdiEventConsumer<T> consumer) {
+        synchronized (consumers) {
+            consumers.add(consumer);
+        }
+    }
+
+    void unregisterConsumer(CdiEventConsumer<T> consumer) {
+        synchronized (consumers) {
+            consumers.remove(consumer);
+        }
+    }
+
+    void notify(T t) {
+        synchronized (consumers) {
+            for (CdiEventConsumer<T> consumer : consumers) {
+                consumer.notify(t);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
new file mode 100644
index 0000000..e9d27e7
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
@@ -0,0 +1,47 @@
+/**
+ * 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;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.EventObject;
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.support.EventNotifierSupport;
+
+final class CdiEventNotifier extends EventNotifierSupport {
+
+    private final BeanManager manager;
+
+    private final Annotation[] qualifiers;
+
+    CdiEventNotifier(BeanManager manager, Collection<Annotation> qualifiers) {
+        this.manager = manager;
+        this.qualifiers = qualifiers.toArray(new Annotation[qualifiers.size()]);
+        // TODO: be more fine grained for the kind of events that are emitted depending on the observed event types
+    }
+
+    @Override
+    public void notify(EventObject event) {
+        manager.fireEvent(event, qualifiers);
+    }
+
+    @Override
+    public boolean isEnabled(EventObject event) {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
new file mode 100644
index 0000000..11cb274
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
@@ -0,0 +1,47 @@
+/**
+ * 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;
+
+import javax.enterprise.event.Event;
+import org.apache.camel.Exchange;
+
+import org.apache.camel.impl.DefaultProducer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* package-private */ final class CdiEventProducer<T> extends DefaultProducer {
+
+    private final Logger logger = LoggerFactory.getLogger(CdiEventProducer.class);
+
+    private final Event<T> event;
+
+    CdiEventProducer(CdiEventEndpoint<T> endpoint, Event<T> event) {
+        super(endpoint);
+        this.event = event;
+    }
+
+    @Override
+    public void process(Exchange exchange) {
+        logger.debug("Firing CDI event [{}] with {}", event, this);
+        // TODO: leverage Camel type converter mechanism based on the endpoint type
+        // The EventMetadata injection point will be that of the event which is not very useful
+        // for the end user. Using BeanManager.fire would be a way to hide that internal though
+        // it will be necessary to check whether the exchange event type is assignable to the
+        // endpoint event type.
+        event.fire((T) exchange.getIn().getBody());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
deleted file mode 100644
index afb3a49..0000000
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
+++ /dev/null
@@ -1,62 +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.cdi;
-
-import org.apache.camel.IsSingleton;
-import org.apache.camel.spi.Injector;
-import org.apache.camel.util.ReflectionInjector;
-import org.apache.deltaspike.core.api.provider.BeanProvider;
-
-/**
- * Injector implementation which performs injection with CDI bean provider.
- */
-public class CdiInjector implements Injector {
-
-    /**
-     * Fallback injector used when there is bean of given type registered in CDI.
-     */
-    private Injector injector;
-
-    public CdiInjector() {
-        this(new ReflectionInjector());
-    }
-
-    public CdiInjector(Injector parent) {
-        this.injector = parent;
-    }
-
-    @Override
-    public <T> T newInstance(Class<T> type) {
-        T bean = BeanProvider.getContextualReference(type, true);
-        if (bean != null) {
-            return type.cast(bean);
-        }
-        return injector.newInstance(type);
-    }
-
-    @Override
-    public <T> T newInstance(Class<T> type, Object instance) {
-        if (instance instanceof IsSingleton) {
-            boolean singleton = ((IsSingleton) instance).isSingleton();
-            if (singleton) {
-                return type.cast(instance);
-            }
-        }
-        return newInstance(type);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
new file mode 100644
index 0000000..5bf852e
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
@@ -0,0 +1,143 @@
+/**
+ * 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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.camel.util.ObjectHelper;
+
+@Vetoed
+final class CdiSpiHelper {
+
+    private CdiSpiHelper() {
+    }
+
+    static <T extends Annotation> T getQualifierByType(InjectionPoint ip, Class<T> type) {
+        return getFirstElementOfType(ip.getQualifiers(), type);
+    }
+
+    private static <E, T extends E> T getFirstElementOfType(Collection<E> collection, Class<T> type) {
+        for (E item : collection) {
+            if ((item != null) && type.isAssignableFrom(item.getClass())) {
+                return ObjectHelper.cast(type, item);
+            }
+        }
+        return null;
+    }
+
+    @SafeVarargs
+    static <T> Set<T> excludeElementOfTypes(Set<T> annotations, Class<? extends T>... exclusions) {
+        Set<T> set = new HashSet<>();
+        for (T qualifier : annotations) {
+            boolean exclude = false;
+            for (Class<? extends T> exclusion : exclusions) {
+                if (exclusion.isAssignableFrom(qualifier.getClass())) {
+                    exclude = true;
+                    break;
+                }
+            }
+            if (!exclude) {
+                set.add(qualifier);
+            }
+        }
+        return set;
+    }
+
+    static Class<?> getRawType(Type type) {
+        if (type instanceof Class<?>) {
+            return Class.class.cast(type);
+        } else if (type instanceof ParameterizedType) {
+            return getRawType(ParameterizedType.class.cast(type).getRawType());
+        } else if (type instanceof TypeVariable<?>) {
+            return getBound(TypeVariable.class.cast(type).getBounds());
+        } else if (type instanceof WildcardType) {
+            return getBound(WildcardType.class.cast(type).getUpperBounds());
+        } else if (type instanceof GenericArrayType) {
+            Class<?> rawType = getRawType(GenericArrayType.class.cast(type).getGenericComponentType());
+            if (rawType != null) {
+                return Array.newInstance(rawType, 0).getClass();
+            }
+        }
+        throw new UnsupportedOperationException("Unable to retrieve raw type for [" + type + "]");
+    }
+
+    private static Class<?> getBound(Type[] bounds) {
+        if (bounds.length == 0) {
+            return Object.class;
+        } else {
+            return getRawType(bounds[0]);
+        }
+    }
+
+    @SafeVarargs
+    static boolean hasAnnotation(AnnotatedType<?> type, Class<? extends Annotation>... annotations) {
+        for (Class<? extends Annotation> annotation : annotations) {
+            if (hasAnnotation(type, annotation)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean hasAnnotation(AnnotatedType<?> type, Class<? extends Annotation> annotation) {
+        if (type.isAnnotationPresent(annotation)) {
+            return true;
+        }
+        for (AnnotatedMethod<?> method : type.getMethods()) {
+            if (method.isAnnotationPresent(annotation)) {
+                return true;
+            }
+        }
+        for (AnnotatedConstructor<?> constructor : type.getConstructors()) {
+            if (constructor.isAnnotationPresent(annotation)) {
+                return true;
+            }
+        }
+        for (AnnotatedField<?> field : type.getFields()) {
+            if (field.isAnnotationPresent(annotation)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static Set<Annotation> getQualifiers(Annotated annotated, BeanManager manager) {
+        Set<Annotation> qualifiers = new HashSet<>();
+        for (Annotation annotation : annotated.getAnnotations()) {
+            if (manager.isQualifier(annotation.annotationType())) {
+                qualifiers.add(annotation);
+            }
+        }
+        return qualifiers;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
new file mode 100644
index 0000000..b8991e6
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
@@ -0,0 +1,33 @@
+/**
+ * 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;
+
+import org.apache.camel.impl.converter.AnnotationTypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+@Vetoed
+final class CdiTypeConverterLoader extends AnnotationTypeConverterLoader {
+
+    CdiTypeConverterLoader() {
+        super(null);
+    }
+
+    @Override
+    protected void loadConverterMethods(TypeConverterRegistry registry, Class<?> type) {
+        super.loadConverterMethods(registry, type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
index f34cb49..2006e71 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
@@ -1,40 +1,91 @@
-/**
- * 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;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.builder.RouteBuilder;
-
-/**
- * Used to bind objects to a named {@link CamelContext} instance 
- * such as {@link RouteBuilder} instances.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
-public @interface ContextName {
-
-    /**
-     * Returns the name of the CamelContext to add the routes to.
-     * If no value is specified then the default CamelContext is used.
-     */
-    String value() default "";
-}
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+/**
+ * CDI qualifier to be used for multi Camel contexts CDI deployment.
+ * {@code CamelContext} beans can be annotated with the {@code @ContextName} qualifier
+ * so that the Camel context is named accordingly, e.g.:
+ *
+ * <pre><code>
+ * {@literal @}ApplicationScoped
+ * {@literal @}ContextName("foo")
+ * public class FooCamelContext extends DefaultCamelContext {
+ * }
+ * </code></pre>
+ *
+ * Camel resources like route builders, endpoints and producer templates can be annotated with
+ * the {@code @ContextName} qualifier as well so that they are associated with the
+ * corresponding Camel context, e.g.:
+ *
+ * <pre><code>
+ * {@literal @}ContextName("foo")
+ * public class FooRouteBuilder extends RouteBuilder {
+ *
+ *     {@literal @}Override
+ *     public void configure() {
+ *         from("direct:bar").to("mock:bar");
+ *     }
+ * }
+ *
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * {@literal @}Uri("direct:bar")
+ * ProducerTemplate barProducer;
+ *
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * {@literal @}Uri("mock:bar")
+ * MockEndpoint barMockEndpoint;
+ * </code></pre>
+ *
+ * @see org.apache.camel.CamelContext
+ *
+ */
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
+public @interface ContextName {
+
+    /**
+     * Returns the name of the Camel context.
+     */
+    String value();
+
+    final class Literal extends AnnotationLiteral<ContextName> implements ContextName {
+
+        private static final long serialVersionUID = 1L;
+
+        private final String name;
+
+        public Literal(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String value() {
+            return name;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
new file mode 100644
index 0000000..c78d6c0
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
@@ -0,0 +1,31 @@
+/**
+ * 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;
+
+import javax.enterprise.inject.Default;
+import javax.enterprise.util.AnnotationLiteral;
+
+@Vetoed
+final class DefaultLiteral extends AnnotationLiteral<Default> implements Default {
+
+    static final Default INSTANCE = new DefaultLiteral();
+
+    private static final long serialVersionUID = 1L;
+
+    private DefaultLiteral() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
new file mode 100644
index 0000000..9fef662
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
@@ -0,0 +1,51 @@
+/**
+ * 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;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Producer;
+
+abstract class DelegateInjectionTarget<T> extends DelegateProducer<T> implements InjectionTarget<T> {
+
+    private final InjectionTarget<T> delegate;
+
+    DelegateInjectionTarget(InjectionTarget<T> delegate) {
+        super(delegate);
+        this.delegate = delegate;
+    }
+
+    DelegateInjectionTarget(InjectionTarget<T> target, Producer<T> producer) {
+        super(producer);
+        this.delegate = target;
+    }
+
+    @Override
+    public void inject(T instance, CreationalContext<T> ctx) {
+        delegate.inject(instance, ctx);
+    }
+
+    @Override
+    public void postConstruct(T instance) {
+        delegate.postConstruct(instance);
+    }
+
+    @Override
+    public void preDestroy(T instance) {
+        delegate.preDestroy(instance);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
new file mode 100644
index 0000000..05f8516
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
@@ -0,0 +1,51 @@
+/**
+ * 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;
+
+import java.util.Set;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.Producer;
+
+abstract class DelegateProducer<T> implements Producer<T> {
+
+    private final Producer<T> delegate;
+
+    DelegateProducer(Producer<T> delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public T produce(CreationalContext<T> ctx) {
+        return delegate.produce(ctx);
+    }
+
+    @Override
+    public void dispose(T instance) {
+        delegate.dispose(instance);
+    }
+
+    @Override
+    public Set<InjectionPoint> getInjectionPoints() {
+        return delegate.getInjectionPoints();
+    }
+
+    @Override
+    public String toString() {
+        return delegate.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
new file mode 100644
index 0000000..eccf446
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
@@ -0,0 +1,40 @@
+/**
+ * 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;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(value = RUNTIME)
+@Target(value = { TYPE, METHOD, PARAMETER, FIELD })
+@interface Excluded {
+
+    Excluded INSTANCE = new ExcludedLiteral();
+
+    final class ExcludedLiteral extends AnnotationLiteral<Excluded>implements Excluded {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
new file mode 100644
index 0000000..3f2b565
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
@@ -0,0 +1,78 @@
+/**
+ * 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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.enterprise.event.Reception;
+import javax.enterprise.event.TransactionPhase;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.camel.CamelContext;
+
+/* package-private */ final class ForwardingObserverMethod<T> implements ObserverMethod<T> {
+
+    // Should be replaced with the Java 8 functional interface Consumer<T>
+    private final AtomicReference<CdiEventEndpoint<T>> observer = new AtomicReference<>();
+
+    private final Type type;
+
+    private final Set<Annotation> qualifiers;
+
+    ForwardingObserverMethod(Type type, Set<Annotation> qualifiers) {
+        this.type = type;
+        this.qualifiers = qualifiers;
+    }
+
+    void setObserver(CdiEventEndpoint<T> observer) {
+        this.observer.set(observer);
+    }
+
+    @Override
+    public Class<?> getBeanClass() {
+        return CamelContext.class;
+    }
+
+    @Override
+    public Type getObservedType() {
+        return type;
+    }
+
+    @Override
+    public Set<Annotation> getObservedQualifiers() {
+        return qualifiers;
+    }
+
+    @Override
+    public Reception getReception() {
+        return Reception.ALWAYS;
+    }
+
+    @Override
+    public TransactionPhase getTransactionPhase() {
+        return TransactionPhase.IN_PROGRESS;
+    }
+
+    @Override
+    public void notify(T event) {
+        if (observer.get() != null) {
+            observer.get().notify(event);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/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 0532870..cd55010 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
@@ -17,37 +17,42 @@
 package org.apache.camel.cdi;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import javax.xml.bind.JAXBContext;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
-import org.apache.camel.impl.DefaultModelJAXBContextFactory;
 import org.apache.camel.main.MainSupport;
-import org.apache.camel.spi.ModelJAXBContextFactory;
-import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.cdise.api.CdiContainer;
 
 /**
- * Allows Camel and CDI applications to be booted up on the command line as a Java Application
+ * Camel CDI boot integration. Allows Camel and CDI to be booted up on the command line as a JVM process.
+ * See http://camel.apache.org/camel-boot.html.
  */
-public abstract class Main extends MainSupport { // abstract to prevent cdi management
-    private static Main instance;
-    private JAXBContext jaxbContext;
-    private Object cdiContainer; // we don't want to need cdictrl API in OSGi
+@Vetoed
+public class Main extends MainSupport {
 
-    public Main() {
-        // add options...
+    static {
+        // Since version 2.3.0.Final and WELD-1915, Weld SE registers a shutdown hook that conflicts
+        // with Camel main support. See WELD-2051. The system property above is available starting
+        // Weld 2.3.1.Final to deactivate the registration of the shutdown hook.
+        System.setProperty("org.jboss.weld.se.shutdownHook", String.valueOf(Boolean.FALSE));
     }
 
+    private static Main instance;
+
+    private CdiContainer cdiContainer;
+
     public static void main(String... args) throws Exception {
-        Main main = new Main() { };
+        Main main = new Main();
         instance = main;
         main.run(args);
     }
 
     /**
-     * Returns the currently executing main
+     * Returns the currently executing instance.
      *
      * @return the current running instance
      */
@@ -57,46 +62,42 @@ public abstract class Main extends MainSupport { // abstract to prevent cdi mana
 
     @Override
     protected ProducerTemplate findOrCreateCamelTemplate() {
-        ProducerTemplate answer = BeanProvider.getContextualReference(ProducerTemplate.class, true);
-        if (answer != null) {
-            return answer;
+        BeanManager manager = cdiContainer.getBeanManager();
+        Bean<?> bean = manager.resolve(manager.getBeans(CamelContext.class));
+        if (bean == null) {
+            throw new UnsatisfiedResolutionException("No default Camel context is deployed, cannot create default ProducerTemplate!");
         }
-        if (getCamelContexts().isEmpty()) {
-            throw new IllegalArgumentException(
-                    "No CamelContexts are available so cannot create a ProducerTemplate!");
-        }
-        return getCamelContexts().get(0).createProducerTemplate();
+        CamelContext context = (CamelContext) manager.getReference(bean, CamelContext.class, manager.createCreationalContext(bean));
+        return context.createProducerTemplate();
     }
 
     @Override
     protected Map<String, CamelContext> getCamelContextMap() {
-        List<CamelContext> contexts = BeanProvider.getContextualReferences(CamelContext.class, true);
-        Map<String, CamelContext> answer = new HashMap<String, CamelContext>();
-        for (CamelContext context : contexts) {
-            String name = context.getName();
-            answer.put(name, context);
+        BeanManager manager = cdiContainer.getBeanManager();
+        Map<String, CamelContext> answer = new HashMap<>();
+        for (Bean<?> bean : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+            CamelContext context = (CamelContext) manager.getReference(bean, CamelContext.class, manager.createCreationalContext(bean));
+            answer.put(context.getName(), context);
         }
         return answer;
     }
 
-    public ModelJAXBContextFactory getModelJAXBContextFactory() {
-        return new DefaultModelJAXBContextFactory();
-    }
-
     @Override
     protected void doStart() throws Exception {
+        // TODO: Use standard CDI Java SE support when CDI 2.0 becomes a prerequisite
         org.apache.deltaspike.cdise.api.CdiContainer container = org.apache.deltaspike.cdise.api.CdiContainerLoader.getCdiContainer();
         container.boot();
         container.getContextControl().startContexts();
         cdiContainer = container;
         super.doStart();
+        postProcessContext();
     }
 
     @Override
     protected void doStop() throws Exception {
         super.doStop();
         if (cdiContainer != null) {
-            ((org.apache.deltaspike.cdise.api.CdiContainer) cdiContainer).shutdown();
+            cdiContainer.shutdown();
         }
     }
 }