This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch bind in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8412ba2b4f64b2ae8f280f190b0cc146083c4f4a Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Mar 4 10:01:11 2019 +0100 CAMEL-13283: Add @BindRegistry annotation to allow to bind beans/classes to registry. --- .../main/java/org/apache/camel/BindRegistry.java | 37 ++++++++++++++++++++++ .../camel/impl/DefaultCamelBeanPostProcessor.java | 28 ++++++++++++++++ .../impl/DefaultCamelBeanPostProcessorTest.java | 13 ++++++++ .../org/apache/camel/util/ReflectionHelper.java | 18 +++++++++++ 4 files changed, 96 insertions(+) diff --git a/core/camel-api/src/main/java/org/apache/camel/BindRegistry.java b/core/camel-api/src/main/java/org/apache/camel/BindRegistry.java new file mode 100644 index 0000000..b2aebca --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/BindRegistry.java @@ -0,0 +1,37 @@ +/** + * 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; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used for binding a bean to the registry + * + * If no name is specified then the bean will have its name auto computed based on the + * field name, or method name where the annotation is configured. + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) +public @interface BindRegistry { + String name() default ""; + String context() default ""; +} diff --git a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelBeanPostProcessor.java b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelBeanPostProcessor.java index 8b77e86..e7dc03f 100644 --- a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelBeanPostProcessor.java +++ b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelBeanPostProcessor.java @@ -20,6 +20,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import org.apache.camel.BeanInject; +import org.apache.camel.BindRegistry; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.DeferredContextBinding; @@ -32,6 +33,8 @@ import org.apache.camel.util.ReflectionHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.camel.util.ObjectHelper.isEmpty; + /** * A bean post processor which implements the <a href="http://camel.apache.org/bean-integration.html">Bean Integration</a> * features in Camel. Features such as the <a href="http://camel.apache.org/bean-injection.html">Bean Injection</a> of objects like @@ -84,6 +87,16 @@ public class DefaultCamelBeanPostProcessor { injectFields(bean, beanName); injectMethods(bean, beanName); + // the bean may also need to be registered into the registry + BindRegistry bind = bean.getClass().getAnnotation(BindRegistry.class); + if (bind != null) { + String name = bind.name(); + if (isEmpty(name)) { + name = bean.getClass().getSimpleName(); + } + camelContext.getRegistry().bind(name, bean); + } + if (bean instanceof CamelContextAware && canSetCamelContext(bean, beanName)) { CamelContextAware contextAware = (CamelContextAware)bean; DeferredContextBinding deferredBinding = bean.getClass().getAnnotation(DeferredContextBinding.class); @@ -189,10 +202,25 @@ public class DefaultCamelBeanPostProcessor { if (produce != null && getPostProcessorHelper().matchContext(produce.context())) { injectField(field, produce.uri(), produce.ref(), produce.property(), bean, beanName, produce.binding()); } + + BindRegistry bind = field.getAnnotation(BindRegistry.class); + if (bind != null && getPostProcessorHelper().matchContext(bind.context())) { + bindRegistry(field, bind.name(), bean, beanName); + } } }); } + private void bindRegistry(Field field, String name, Object bean, String beanName) { + if (isEmpty(name)) { + name = field.getName(); + } + Object value = ReflectionHelper.getField(field, bean); + if (value != null) { + camelContext.getRegistry().bind(name, value); + } + } + public void injectField(Field field, String endpointUri, String endpointRef, String endpointProperty, Object bean, String beanName) { injectField(field, endpointUri, endpointRef, endpointProperty, bean, beanName, true); diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorTest.java index 006be1a..f6b7ef8 100644 --- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorTest.java @@ -15,6 +15,8 @@ * limitations under the License. */ package org.apache.camel.impl; + +import org.apache.camel.BindRegistry; import org.apache.camel.Consume; import org.apache.camel.ContextTestSupport; import org.apache.camel.Produce; @@ -38,6 +40,14 @@ public class DefaultCamelBeanPostProcessorTest extends ContextTestSupport { getMockEndpoint("mock:result").expectedMessageCount(1); template.sendBody("seda:input", "Hello World"); assertMockEndpointsSatisfied(); + + // should register the beans in the registry via @BindRegistry + Object bean = context.getRegistry().lookupByName("myCoolBean"); + assertNotNull(bean); + assertIsInstanceOf(MySerialBean.class, bean); + bean = context.getRegistry().lookupByName("FooService"); + assertNotNull(bean); + assertIsInstanceOf(FooService.class, bean); } @Override @@ -47,12 +57,15 @@ public class DefaultCamelBeanPostProcessorTest extends ContextTestSupport { postProcessor = new DefaultCamelBeanPostProcessor(context); } + @BindRegistry public class FooService { private String fooEndpoint; private String barEndpoint; @Produce private ProducerTemplate bar; + @BindRegistry(name = "myCoolBean") + private MySerialBean myBean = new MySerialBean(); public String getFooEndpoint() { return fooEndpoint; diff --git a/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java index 0a4b8cf..e36aa98 100644 --- a/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java +++ b/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java @@ -157,4 +157,22 @@ public final class ReflectionHelper { } } + public static Object getField(Field f, Object instance) { + try { + boolean oldAccessible = f.isAccessible(); + boolean shouldSetAccessible = !Modifier.isPublic(f.getModifiers()) && !oldAccessible; + if (shouldSetAccessible) { + f.setAccessible(true); + } + Object answer = f.get(instance); + if (shouldSetAccessible) { + f.setAccessible(oldAccessible); + } + return answer; + } catch (Exception ex) { + // ignore + } + return null; + } + }