CAMEL-5402: Camel proxy allows to bind to method interface using @Body @Header and @ExchangeProperty to bind arguments to the exchange
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/32b6c514 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/32b6c514 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/32b6c514 Branch: refs/heads/master Commit: 32b6c514f270d24d3d281124d229ffbe141d4996 Parents: 178b84d Author: Claus Ibsen <davscl...@apache.org> Authored: Mon Aug 10 18:30:33 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Aug 10 18:30:33 2015 +0200 ---------------------------------------------------------------------- .../org/apache/camel/builder/ProxyBuilder.java | 18 +++++- .../bean/AbstractCamelInvocationHandler.java | 54 ++++++++---------- .../component/bean/CamelInvocationHandler.java | 9 ++- .../camel/component/bean/ProxyHelper.java | 59 ++++++++++++++++++-- .../component/bean/MyAuditServiceProxyTest.java | 3 +- 5 files changed, 106 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/32b6c514/camel-core/src/main/java/org/apache/camel/builder/ProxyBuilder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/ProxyBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ProxyBuilder.java index 33c04d3..523f420 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/ProxyBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/builder/ProxyBuilder.java @@ -30,6 +30,7 @@ public final class ProxyBuilder { private final CamelContext camelContext; private Endpoint endpoint; + private boolean binding; public ProxyBuilder(CamelContext camelContext) { this.camelContext = camelContext; @@ -58,6 +59,21 @@ public final class ProxyBuilder { } /** + * Whether to use binding or not. + * <p/> + * If binding is enabled then Camel will bind the method parameters to the input {@link org.apache.camel.Message} + * on the {@link org.apache.camel.Exchange} when invoking the proxy. + * + * @param binding <tt>true</tt> to use binding, <tt>false</tt> to use the old behavior with using a {@link org.apache.camel.component.bean.BeanInvocation} + * as a provisional message body + * @return the builder + */ + public ProxyBuilder binding(boolean binding) { + this.binding = binding; + return this; + } + + /** * Builds the proxy. * * @param interfaceClass the service interface @@ -81,7 +97,7 @@ public final class ProxyBuilder { */ public <T> T build(Class<T>... interfaceClasses) throws Exception { ObjectHelper.notNull(endpoint, "endpoint"); - return ProxyHelper.createProxy(endpoint, interfaceClasses); + return ProxyHelper.createProxy(endpoint, binding, interfaceClasses); } } http://git-wip-us.apache.org/repos/asf/camel/blob/32b6c514/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java b/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java index 3677c11..69e9f8c 100644 --- a/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java +++ b/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java @@ -99,45 +99,39 @@ public abstract class AbstractCamelInvocationHandler implements InvocationHandle public abstract Object doInvokeProxy(final Object proxy, final Method method, final Object[] args) throws Throwable; - protected Object invokeProxy(final Method method, final ExchangePattern pattern, Object[] args) throws Throwable { + protected Object invokeProxy(final Method method, final ExchangePattern pattern, Object[] args, boolean binding) throws Throwable { final Exchange exchange = new DefaultExchange(endpoint, pattern); // use method info to map to exchange - // we support @Header, @Body and @ExchangeProperty to map to Exchange - boolean found = false; - - int index = 0; - for (Annotation[] row : method.getParameterAnnotations()) { - Object value = args[index]; - for (Annotation ann : row) { - if (ann.annotationType().isAssignableFrom(Header.class)) { - Header header = (Header) ann; - String name = header.value(); - exchange.getIn().setHeader(name, value); - found = true; - } else if (ann.annotationType().isAssignableFrom(ExchangeProperty.class)) { - ExchangeProperty ep = (ExchangeProperty) ann; - String name = ep.value(); - exchange.setProperty(name, value); - found = true; - } else if (ann.annotationType().isAssignableFrom(Body.class)) { - exchange.getIn().setBody(value); - found = true; - } else { - // assume its message body when there is no annotations - exchange.getIn().setBody(value); + if (binding) { + int index = 0; + for (Annotation[] row : method.getParameterAnnotations()) { + Object value = args[index]; + for (Annotation ann : row) { + if (ann.annotationType().isAssignableFrom(Header.class)) { + Header header = (Header) ann; + String name = header.value(); + exchange.getIn().setHeader(name, value); + } else if (ann.annotationType().isAssignableFrom(ExchangeProperty.class)) { + ExchangeProperty ep = (ExchangeProperty) ann; + String name = ep.value(); + exchange.setProperty(name, value); + } else if (ann.annotationType().isAssignableFrom(Body.class)) { + exchange.getIn().setBody(value); + } else { + // assume its message body when there is no annotations + exchange.getIn().setBody(value); + } } + index++; } - index++; - } - - // backwards compatible where the body is a BeanInvocation - if (!found) { + } else { + // no binding so use the old behavior with BeanInvocation as the body BeanInvocation invocation = new BeanInvocation(method, args); exchange.getIn().setBody(invocation); } - if (found) { + if (binding) { LOG.trace("Binding to service interface as @Body,@Header,@ExchangeProperty detected when calling proxy method: {}", method); } else { LOG.trace("No binding to service interface as @Body,@Header,@ExchangeProperty not detected. Using BeanInvocation as message body when calling proxy method: {}"); http://git-wip-us.apache.org/repos/asf/camel/blob/32b6c514/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java b/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java index 120b6b0..0b45b3f22 100644 --- a/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java +++ b/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java @@ -31,9 +31,16 @@ import org.apache.camel.Producer; */ public class CamelInvocationHandler extends AbstractCamelInvocationHandler implements InvocationHandler { private final MethodInfoCache methodInfoCache; + private final boolean binding; + @Deprecated public CamelInvocationHandler(Endpoint endpoint, Producer producer, MethodInfoCache methodInfoCache) { + this(endpoint, false, producer, methodInfoCache); + } + + public CamelInvocationHandler(Endpoint endpoint, boolean binding, Producer producer, MethodInfoCache methodInfoCache) { super(endpoint, producer); + this.binding = binding; this.methodInfoCache = methodInfoCache; } @@ -41,7 +48,7 @@ public class CamelInvocationHandler extends AbstractCamelInvocationHandler imple public Object doInvokeProxy(Object proxy, Method method, Object[] args) throws Throwable { MethodInfo methodInfo = methodInfoCache.getMethodInfo(method); final ExchangePattern pattern = methodInfo != null ? methodInfo.getPattern() : ExchangePattern.InOut; - return invokeProxy(method, pattern, args); + return invokeProxy(method, pattern, args, binding); } } http://git-wip-us.apache.org/repos/asf/camel/blob/32b6c514/camel-core/src/main/java/org/apache/camel/component/bean/ProxyHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/ProxyHelper.java b/camel-core/src/main/java/org/apache/camel/component/bean/ProxyHelper.java index d51cf18..f80a9a9 100644 --- a/camel-core/src/main/java/org/apache/camel/component/bean/ProxyHelper.java +++ b/camel-core/src/main/java/org/apache/camel/component/bean/ProxyHelper.java @@ -37,15 +37,29 @@ public final class ProxyHelper { /** * Creates a Proxy which sends the exchange to the endpoint. + * + * @deprecated use the same method name with binding as parameter */ @SuppressWarnings("unchecked") + @Deprecated public static <T> T createProxyObject(Endpoint endpoint, Producer producer, ClassLoader classLoader, Class<T>[] interfaces, MethodInfoCache methodCache) { - return (T) Proxy.newProxyInstance(classLoader, interfaces.clone(), new CamelInvocationHandler(endpoint, producer, methodCache)); + return createProxyObject(endpoint, false, producer, classLoader, interfaces, methodCache); } /** * Creates a Proxy which sends the exchange to the endpoint. */ + @SuppressWarnings("unchecked") + public static <T> T createProxyObject(Endpoint endpoint, boolean binding, Producer producer, ClassLoader classLoader, Class<T>[] interfaces, MethodInfoCache methodCache) { + return (T) Proxy.newProxyInstance(classLoader, interfaces.clone(), new CamelInvocationHandler(endpoint, binding, producer, methodCache)); + } + + /** + * Creates a Proxy which sends the exchange to the endpoint. + * + * @deprecated use the same method name with binding as parameter + */ + @Deprecated public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T> interfaceClass, MethodInfoCache methodCache) throws Exception { return createProxy(endpoint, cl, toArray(interfaceClass), methodCache); } @@ -53,10 +67,27 @@ public final class ProxyHelper { /** * Creates a Proxy which sends the exchange to the endpoint. */ + public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T> interfaceClass, MethodInfoCache methodCache) throws Exception { + return createProxy(endpoint, binding, cl, toArray(interfaceClass), methodCache); + } + + /** + * Creates a Proxy which sends the exchange to the endpoint. + * + * @deprecated use the same method name with binding as parameter + */ + @Deprecated public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>[] interfaceClasses, MethodInfoCache methodCache) throws Exception { + return createProxy(endpoint, false, cl, interfaceClasses, methodCache); + } + + /** + * Creates a Proxy which sends the exchange to the endpoint. + */ + public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T>[] interfaceClasses, MethodInfoCache methodCache) throws Exception { Producer producer = DeferServiceFactory.createProducer(endpoint); endpoint.getCamelContext().deferStartService(producer, true); - return createProxyObject(endpoint, producer, cl, interfaceClasses, methodCache); + return createProxyObject(endpoint, binding, producer, cl, interfaceClasses, methodCache); } /** @@ -68,9 +99,19 @@ public final class ProxyHelper { /** * Creates a Proxy which sends the exchange to the endpoint. + * + * @deprecated use the same method name with binding as parameter */ + @Deprecated public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>... interfaceClasses) throws Exception { - return createProxy(endpoint, cl, interfaceClasses, createMethodInfoCache(endpoint)); + return createProxy(endpoint, false, cl, interfaceClasses); + } + + /** + * Creates a Proxy which sends the exchange to the endpoint. + */ + public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T>... interfaceClasses) throws Exception { + return createProxy(endpoint, binding, cl, interfaceClasses, createMethodInfoCache(endpoint)); } /** @@ -82,9 +123,19 @@ public final class ProxyHelper { /** * Creates a Proxy which sends the exchange to the endpoint. + * + * @deprecated use the same method name with binding as parameter */ + @Deprecated public static <T> T createProxy(Endpoint endpoint, Class<T>... interfaceClasses) throws Exception { - return createProxy(endpoint, getClassLoader(interfaceClasses), interfaceClasses); + return createProxy(endpoint, false, interfaceClasses); + } + + /** + * Creates a Proxy which sends the exchange to the endpoint. + */ + public static <T> T createProxy(Endpoint endpoint, boolean binding, Class<T>... interfaceClasses) throws Exception { + return createProxy(endpoint, binding, getClassLoader(interfaceClasses), interfaceClasses); } /** http://git-wip-us.apache.org/repos/asf/camel/blob/32b6c514/camel-core/src/test/java/org/apache/camel/component/bean/MyAuditServiceProxyTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/MyAuditServiceProxyTest.java b/camel-core/src/test/java/org/apache/camel/component/bean/MyAuditServiceProxyTest.java index daa351b..43ee38d 100644 --- a/camel-core/src/test/java/org/apache/camel/component/bean/MyAuditServiceProxyTest.java +++ b/camel-core/src/test/java/org/apache/camel/component/bean/MyAuditServiceProxyTest.java @@ -26,7 +26,8 @@ public class MyAuditServiceProxyTest extends ContextTestSupport { getMockEndpoint("mock:result").expectedBodiesReceived("Hello World"); getMockEndpoint("mock:result").expectedHeaderReceived("uuid", "1234"); - MyAuditService service = new ProxyBuilder(context).endpoint("direct:proxy").build(MyAuditService.class); + // must enable binding on proxy + MyAuditService service = new ProxyBuilder(context).endpoint("direct:proxy").binding(true).build(MyAuditService.class); service.auditMessage("1234", "Hello World");