Hi

Nice refactor

Just a few suggestion for polishing
- the logger in the abstract class is using the other class name
- possible add a bit javadoc to the abstract class
- a method has xxxbody where body is with a little b, and not Body.


On Mon, Oct 24, 2011 at 4:51 PM,  <cschnei...@apache.org> wrote:
> Author: cschneider
> Date: Mon Oct 24 14:51:12 2011
> New Revision: 1188162
>
> URL: http://svn.apache.org/viewvc?rev=1188162&view=rev
> Log:
> CAMEL-4565 Code and tests for sending simple objects from a dynamic proxy
>
> Added:
>    
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java
>    (with props)
>    
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java
>    (with props)
>    
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java
>    (with props)
>    
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/
>    
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java
>    (with props)
>    
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java
>    (with props)
>    
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java
>    (with props)
> Modified:
>    
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
>
> Added: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java
>  Mon Oct 24 14:51:12 2011
> @@ -0,0 +1,217 @@
> +/**
> + * 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.component.bean;
> +
> +import java.lang.reflect.InvocationHandler;
> +import java.lang.reflect.Method;
> +import java.lang.reflect.Type;
> +import java.util.concurrent.Callable;
> +import java.util.concurrent.ExecutionException;
> +import java.util.concurrent.ExecutorService;
> +import java.util.concurrent.Future;
> +import java.util.concurrent.FutureTask;
> +
> +import org.apache.camel.CamelContext;
> +import org.apache.camel.CamelExchangeException;
> +import org.apache.camel.Endpoint;
> +import org.apache.camel.Exchange;
> +import org.apache.camel.ExchangePattern;
> +import org.apache.camel.InvalidPayloadException;
> +import org.apache.camel.Producer;
> +import org.apache.camel.RuntimeCamelException;
> +import org.apache.camel.impl.DefaultExchange;
> +import org.apache.camel.util.ObjectHelper;
> +import org.slf4j.Logger;
> +import org.slf4j.LoggerFactory;
> +
> +public abstract class AbstractCamelInvocationHandler implements 
> InvocationHandler {
> +
> +    private static final transient Logger LOG = 
> LoggerFactory.getLogger(CamelInvocationHandler.class);
> +    private static ExecutorService executorService;
> +    protected final Endpoint endpoint;
> +    protected final Producer producer;
> +
> +    public AbstractCamelInvocationHandler(Endpoint endpoint, Producer 
> producer) {
> +        super();
> +        this.endpoint = endpoint;
> +        this.producer = producer;
> +    }
> +
> +    private static Object getBody(Exchange exchange, Class<?> type) throws 
> InvalidPayloadException {
> +        // get the body from the Exchange from either OUT or IN
> +        if (exchange.hasOut()) {
> +            if (exchange.getOut().getBody() != null) {
> +                return exchange.getOut().getMandatoryBody(type);
> +            } else {
> +                return null;
> +            }
> +        } else {
> +            if (exchange.getIn().getBody() != null) {
> +                return exchange.getIn().getMandatoryBody(type);
> +            } else {
> +                return null;
> +            }
> +        }
> +    }
> +
> +    protected Object invokeWithbody(final Method method, Object body, final 
> ExchangePattern pattern) throws InterruptedException, Throwable {
> +        final Exchange exchange = new DefaultExchange(endpoint, pattern);
> +        exchange.getIn().setBody(body);
> +
> +        // is the return type a future
> +        final boolean isFuture = method.getReturnType() == Future.class;
> +
> +        // create task to execute the proxy and gather the reply
> +        FutureTask<Object> task = new FutureTask<Object>(new 
> Callable<Object>() {
> +            public Object call() throws Exception {
> +                // process the exchange
> +                LOG.trace("Proxied method call {} invoking producer: {}", 
> method.getName(), producer);
> +                producer.process(exchange);
> +
> +                Object answer = afterInvoke(method, exchange, pattern, 
> isFuture);
> +                LOG.trace("Proxied method call {} returning: {}", 
> method.getName(), answer);
> +                return answer;
> +            }
> +        });
> +
> +        if (isFuture) {
> +            // submit task and return future
> +            if (LOG.isTraceEnabled()) {
> +                LOG.trace("Submitting task for exchange id {}", 
> exchange.getExchangeId());
> +            }
> +            getExecutorService(exchange.getContext()).submit(task);
> +            return task;
> +        } else {
> +            // execute task now
> +            try {
> +                task.run();
> +                return task.get();
> +            } catch (ExecutionException e) {
> +                // we don't want the wrapped exception from JDK
> +                throw e.getCause();
> +            }
> +        }
> +    }
> +
> +    protected Object afterInvoke(Method method, Exchange exchange, 
> ExchangePattern pattern, boolean isFuture) throws Exception {
> +        // check if we had an exception
> +        Throwable cause = exchange.getException();
> +        if (cause != null) {
> +            Throwable found = findSuitableException(cause, method);
> +            if (found != null) {
> +                if (found instanceof Exception) {
> +                    throw (Exception)found;
> +                } else {
> +                    // wrap as exception
> +                    throw new CamelExchangeException("Error processing 
> exchange", exchange, cause);
> +                }
> +            }
> +            // special for runtime camel exceptions as they can be nested
> +            if (cause instanceof RuntimeCamelException) {
> +                // if the inner cause is a runtime exception we can throw it
> +                // directly
> +                if (cause.getCause() instanceof RuntimeException) {
> +                    throw 
> (RuntimeException)((RuntimeCamelException)cause).getCause();
> +                }
> +                throw (RuntimeCamelException)cause;
> +            }
> +            // okay just throw the exception as is
> +            if (cause instanceof Exception) {
> +                throw (Exception)cause;
> +            } else {
> +                // wrap as exception
> +                throw new CamelExchangeException("Error processing 
> exchange", exchange, cause);
> +            }
> +        }
> +
> +        Class<?> to = isFuture ? getGenericType(exchange.getContext(), 
> method.getGenericReturnType()) : method.getReturnType();
> +
> +        // do not return a reply if the method is VOID
> +        if (to == Void.TYPE) {
> +            return null;
> +        }
> +
> +        return getBody(exchange, to);
> +    }
> +
> +    protected static Class<?> getGenericType(CamelContext context, Type 
> type) throws ClassNotFoundException {
> +        if (type == null) {
> +            // fallback and use object
> +            return Object.class;
> +        }
> +
> +        // unfortunately java dont provide a nice api for getting the generic
> +        // type of the return type
> +        // due type erasure, so we have to gather it based on a String
> +        // representation
> +        String name = ObjectHelper.between(type.toString(), "<", ">");
> +        if (name != null) {
> +            if (name.contains("<")) {
> +                // we only need the outer type
> +                name = ObjectHelper.before(name, "<");
> +            }
> +            return context.getClassResolver().resolveMandatoryClass(name);
> +        } else {
> +            // fallback and use object
> +            return Object.class;
> +        }
> +    }
> +
> +    protected static synchronized ExecutorService 
> getExecutorService(CamelContext context) {
> +        // CamelContext will shutdown thread pool when it shutdown so we can
> +        // lazy create it on demand
> +        // but in case of hot-deploy or the likes we need to be able to
> +        // re-create it (its a shared static instance)
> +        if (executorService == null || executorService.isTerminated() || 
> executorService.isShutdown()) {
> +            // try to lookup a pool first based on id/profile
> +            executorService = 
> context.getExecutorServiceStrategy().lookup(CamelInvocationHandler.class, 
> "CamelInvocationHandler", "CamelInvocationHandler");
> +            if (executorService == null) {
> +                executorService = 
> context.getExecutorServiceStrategy().newDefaultThreadPool(CamelInvocationHandler.class,
>  "CamelInvocationHandler");
> +            }
> +        }
> +        return executorService;
> +    }
> +
> +    /**
> +     * Tries to find the best suited exception to throw.
> +     * <p/>
> +     * It looks in the exception hierarchy from the caused exception and 
> matches
> +     * this against the declared exceptions being thrown on the method.
> +     *
> +     * @param cause the caused exception
> +     * @param method the method
> +     * @return the exception to throw, or <tt>null</tt> if not possible to 
> find
> +     *         a suitable exception
> +     */
> +    protected Throwable findSuitableException(Throwable cause, Method 
> method) {
> +        if (method.getExceptionTypes() == null || 
> method.getExceptionTypes().length == 0) {
> +            return null;
> +        }
> +
> +        // see if there is any exception which matches the declared 
> exception on
> +        // the method
> +        for (Class<?> type : method.getExceptionTypes()) {
> +            Object fault = ObjectHelper.getException(type, cause);
> +            if (fault != null) {
> +                return Throwable.class.cast(fault);
> +            }
> +        }
> +
> +        return null;
> +    }
> +
> +}
>
> Propchange: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/AbstractCamelInvocationHandler.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Modified: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java?rev=1188162&r1=1188161&r2=1188162&view=diff
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
>  (original)
> +++ 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
>  Mon Oct 24 14:51:12 2011
> @@ -18,213 +18,30 @@ package org.apache.camel.component.bean;
>
>  import java.lang.reflect.InvocationHandler;
>  import java.lang.reflect.Method;
> -import java.lang.reflect.Type;
> -import java.util.concurrent.Callable;
> -import java.util.concurrent.ExecutionException;
> -import java.util.concurrent.ExecutorService;
> -import java.util.concurrent.Future;
> -import java.util.concurrent.FutureTask;
>
> -import org.apache.camel.CamelContext;
> -import org.apache.camel.CamelExchangeException;
>  import org.apache.camel.Endpoint;
> -import org.apache.camel.Exchange;
>  import org.apache.camel.ExchangePattern;
> -import org.apache.camel.InvalidPayloadException;
>  import org.apache.camel.Producer;
> -import org.apache.camel.RuntimeCamelException;
> -import org.apache.camel.util.ObjectHelper;
> -import org.slf4j.Logger;
> -import org.slf4j.LoggerFactory;
>
>  /**
> - * An {@link java.lang.reflect.InvocationHandler} which invokes a
> - * message exchange on a camel {@link Endpoint}
> - *
> - * @version
> + * An {@link java.lang.reflect.InvocationHandler} which invokes a message
> + * exchange on a camel {@link Endpoint}
> + *
> + * @version
>  */
> -public class CamelInvocationHandler implements InvocationHandler {
> -    private static final transient Logger LOG = 
> LoggerFactory.getLogger(CamelInvocationHandler.class);
> -
> -    // use a static thread pool to not create a new thread pool for each 
> invocation
> -    private static ExecutorService executorService;
> -
> -    private final Endpoint endpoint;
> -    private final Producer producer;
> +public class CamelInvocationHandler extends AbstractCamelInvocationHandler 
> implements InvocationHandler {
>     private final MethodInfoCache methodInfoCache;
>
>     public CamelInvocationHandler(Endpoint endpoint, Producer producer, 
> MethodInfoCache methodInfoCache) {
> -        this.endpoint = endpoint;
> -        this.producer = producer;
> +        super(endpoint, producer);
>         this.methodInfoCache = methodInfoCache;
>     }
>
>     public Object invoke(final Object proxy, final Method method, final 
> Object[] args) throws Throwable {
>         BeanInvocation invocation = new BeanInvocation(method, args);
>         MethodInfo methodInfo = methodInfoCache.getMethodInfo(method);
> -
>         final ExchangePattern pattern = methodInfo != null ? 
> methodInfo.getPattern() : ExchangePattern.InOut;
> -        final Exchange exchange = endpoint.createExchange(pattern);
> -        exchange.getIn().setBody(invocation);
> -
> -        // is the return type a future
> -        final boolean isFuture = method.getReturnType() == Future.class;
> -
> -        // create task to execute the proxy and gather the reply
> -        FutureTask task = new FutureTask<Object>(new Callable<Object>() {
> -            public Object call() throws Exception {
> -                // process the exchange
> -                LOG.trace("Proxied method call {} invoking producer: {}", 
> method.getName(), producer);
> -                producer.process(exchange);
> -
> -                Object answer = afterInvoke(method, exchange, pattern, 
> isFuture);
> -                LOG.trace("Proxied method call {} returning: {}", 
> method.getName(), answer);
> -                return answer;
> -            }
> -        });
> -
> -        if (isFuture) {
> -            // submit task and return future
> -            if (LOG.isTraceEnabled()) {
> -                LOG.trace("Submitting task for exchange id {}", 
> exchange.getExchangeId());
> -            }
> -            getExecutorService(exchange.getContext()).submit(task);
> -            return task;
> -        } else {
> -            // execute task now
> -            try {
> -                task.run();
> -                return task.get();
> -            } catch (ExecutionException e) {
> -                // we don't want the wrapped exception from JDK
> -                throw e.getCause();
> -            }
> -        }
> -    }
> -
> -    protected Object afterInvoke(Method method, Exchange exchange, 
> ExchangePattern pattern, boolean isFuture) throws Exception {
> -        // check if we had an exception
> -        Throwable cause = exchange.getException();
> -        if (cause != null) {
> -            Throwable found = findSuitableException(cause, method);
> -            if (found != null) {
> -                if (found instanceof Exception) {
> -                    throw (Exception) found;
> -                } else {
> -                    // wrap as exception
> -                    throw new CamelExchangeException("Error processing 
> exchange", exchange, cause);
> -                }
> -            }
> -            // special for runtime camel exceptions as they can be nested
> -            if (cause instanceof RuntimeCamelException) {
> -                // if the inner cause is a runtime exception we can throw it 
> directly
> -                if (cause.getCause() instanceof RuntimeException) {
> -                    throw (RuntimeException) ((RuntimeCamelException) 
> cause).getCause();
> -                }
> -                throw (RuntimeCamelException) cause;
> -            }
> -            // okay just throw the exception as is
> -            if (cause instanceof Exception) {
> -                throw (Exception) cause;
> -            } else {
> -                // wrap as exception
> -                throw new CamelExchangeException("Error processing 
> exchange", exchange, cause);
> -            }
> -        }
> -
> -        // do not return a reply if the method is VOID
> -        Class<?> to = method.getReturnType();
> -        if (to == Void.TYPE) {
> -            return null;
> -        }
> -
> -        // use type converter so we can convert output in the desired type 
> defined by the method
> -        // and let it be mandatory so we know wont return null if we cant 
> convert it to the defined type
> -        Object answer;
> -        if (!isFuture) {
> -            answer = getBody(exchange, to);
> -        } else {
> -            // if its a Future then we need to extract the class from the 
> future type so we know
> -            // which class to return the result as
> -            Class<?> returnTo = getGenericType(exchange.getContext(), 
> method.getGenericReturnType());
> -            answer = getBody(exchange, returnTo);
> -        }
> -
> -        return answer;
> -    }
> -
> -    private static Object getBody(Exchange exchange, Class<?> type) throws 
> InvalidPayloadException {
> -        // get the body from the Exchange from either OUT or IN
> -        if (exchange.hasOut()) {
> -            if (exchange.getOut().getBody() != null) {
> -                return exchange.getOut().getMandatoryBody(type);
> -            } else {
> -                return null;
> -            }
> -        } else {
> -            if (exchange.getIn().getBody() != null) {
> -                return exchange.getIn().getMandatoryBody(type);
> -            } else {
> -                return null;
> -            }
> -        }
> -    }
> -
> -    protected static Class getGenericType(CamelContext context, Type type) 
> throws ClassNotFoundException {
> -        if (type == null) {
> -            // fallback and use object
> -            return Object.class;
> -        }
> -
> -        // unfortunately java dont provide a nice api for getting the 
> generic type of the return type
> -        // due type erasure, so we have to gather it based on a String 
> representation
> -        String name = ObjectHelper.between(type.toString(), "<", ">");
> -        if (name != null) {
> -            if (name.contains("<")) {
> -                // we only need the outer type
> -                name = ObjectHelper.before(name, "<");
> -            }
> -            return context.getClassResolver().resolveMandatoryClass(name);
> -        } else {
> -            // fallback and use object
> -            return Object.class;
> -        }
> -    }
> -
> -    /**
> -     * Tries to find the best suited exception to throw.
> -     * <p/>
> -     * It looks in the exception hierarchy from the caused exception and 
> matches this against the declared exceptions
> -     * being thrown on the method.
> -     *
> -     * @param cause   the caused exception
> -     * @param method  the method
> -     * @return the exception to throw, or <tt>null</tt> if not possible to 
> find a suitable exception
> -     */
> -    protected Throwable findSuitableException(Throwable cause, Method 
> method) {
> -        if (method.getExceptionTypes() == null || 
> method.getExceptionTypes().length == 0) {
> -            return null;
> -        }
> -
> -        // see if there is any exception which matches the declared 
> exception on the method
> -        for (Class<?> type : method.getExceptionTypes()) {
> -            Object fault = ObjectHelper.getException(type, cause);
> -            if (fault != null) {
> -                return Throwable.class.cast(fault);
> -            }
> -        }
> -
> -        return null;
> -    }
> -
> -    protected static synchronized ExecutorService 
> getExecutorService(CamelContext context) {
> -        // CamelContext will shutdown thread pool when it shutdown so we can 
> lazy create it on demand
> -        // but in case of hot-deploy or the likes we need to be able to 
> re-create it (its a shared static instance)
> -        if (executorService == null || executorService.isTerminated() || 
> executorService.isShutdown()) {
> -            executorService = 
> context.getExecutorServiceManager().newDefaultThreadPool(CamelInvocationHandler.class,
>  "CamelInvocationHandler");
> -        }
> -        return executorService;
> +        return invokeWithbody(method, invocation, pattern);
>     }
>
>  }
> -
>
> Added: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java
>  Mon Oct 24 14:51:12 2011
> @@ -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.component.bean;
> +
> +import java.lang.reflect.Method;
> +
> +import org.apache.camel.Endpoint;
> +import org.apache.camel.ExchangePattern;
> +import org.apache.camel.Producer;
> +import org.apache.camel.RuntimeCamelException;
> +
> +/**
> + * Special InvocationHandler for methods that have only one parameter. This
> + * parameter is directly sent to as the body of the message. The idea is to 
> use
> + * that as a very open message format especially when combined with e.g. JAXB
> + * serialization.
> + */
> +public class PojoMessageInvocationHandler extends 
> AbstractCamelInvocationHandler {
> +    public PojoMessageInvocationHandler(Endpoint endpoint, Producer 
> producer) {
> +        super(endpoint, producer);
> +    }
> +
> +    public Object invoke(final Object proxy, final Method method, final 
> Object[] args) throws Throwable {
> +        int argsLength = (args == null) ? 0 : args.length;
> +        if (argsLength != 1) {
> +            throw new RuntimeCamelException(String.format("Error creating 
> proxy for %s.%s Number of arguments must be 1 but is %d",
> +                                                          
> method.getDeclaringClass().getName(),
> +                                                          method.getName(), 
> argsLength));
> +        }
> +        final ExchangePattern pattern = method.getReturnType() != Void.TYPE 
> ? ExchangePattern.InOut : ExchangePattern.InOnly;
> +        return invokeWithbody(method, args[0], pattern);
> +    }
> +
> +}
>
> Propchange: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoMessageInvocationHandler.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Added: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java
>  Mon Oct 24 14:51:12 2011
> @@ -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.component.bean;
> +
> +import java.lang.reflect.Proxy;
> +
> +import org.apache.camel.Endpoint;
> +import org.apache.camel.Producer;
> +import org.apache.camel.util.ServiceHelper;
> +
> +/**
> + * Create a dynamic proxy for a given interface and endpoint that sends the 
> parameter object to the endpoint and optionally
> + * receives a reply. Unlike the ProxyHelper this works only with methods 
> that have only one parameter.
> + */
> +public final class PojoProxyHelper {
> +    private PojoProxyHelper() {
> +    }
> +
> +    @SuppressWarnings("unchecked")
> +    public static <T> T createProxy(Endpoint endpoint, Class<?>... 
> interfaceClasses) throws Exception {
> +        Producer producer = endpoint.createProducer();
> +        // ensure the producer is started
> +        ServiceHelper.startService(producer);
> +        return 
> (T)Proxy.newProxyInstance(ProxyHelper.getClassLoader(interfaceClasses), 
> interfaceClasses.clone(), new PojoMessageInvocationHandler(endpoint, 
> producer));
> +    }
> +}
>
> Propchange: 
> camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/PojoProxyHelper.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Added: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java
>  Mon Oct 24 14:51:12 2011
> @@ -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.component.bean.pojomessage;
> +
> +public class Person {
> +    String name;
> +
> +    public Person() {
> +    }
> +
> +    public Person(String name) {
> +        this.name = name;
> +    }
> +
> +    public String getName() {
> +        return name;
> +    }
> +
> +}
> \ No newline at end of file
>
> Propchange: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/Person.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Added: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java
>  Mon Oct 24 14:51:12 2011
> @@ -0,0 +1,73 @@
> +/**
> + * 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.component.bean.pojomessage;
> +
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +import junit.framework.Assert;
> +
> +import org.apache.camel.ContextTestSupport;
> +import org.apache.camel.Endpoint;
> +import org.apache.camel.builder.RouteBuilder;
> +import org.apache.camel.component.bean.PojoProxyHelper;
> +import org.apache.camel.component.mock.MockEndpoint;
> +import org.junit.Test;
> +
> +public class PojoProxyHelperOneWayTest extends ContextTestSupport {
> +
> +    PersonReceiver receiver = new PersonReceiver();
> +
> +    @Test
> +    public void testOneWay() throws Exception {
> +        Endpoint personEndpoint = context.getEndpoint("direct:person");
> +        MockEndpoint result = 
> (MockEndpoint)context.getEndpoint("mock:result");
> +        Person person = new Person("Chris");
> +        result.expectedBodiesReceived(person);
> +        PersonHandler sender = PojoProxyHelper.createProxy(personEndpoint, 
> PersonHandler.class);
> +
> +        sender.onPerson(person);
> +
> +        result.assertIsSatisfied();
> +        Assert.assertEquals(1, receiver.receivedPersons.size());
> +        Assert.assertEquals(person.getName(), 
> receiver.receivedPersons.get(0).getName());
> +    }
> +
> +    @Override
> +    protected RouteBuilder createRouteBuilder() throws Exception {
> +        return new RouteBuilder() {
> +
> +            @Override
> +            public void configure() throws Exception {
> +                from("direct:person").to("mock:result").bean(receiver);
> +            }
> +        };
> +    }
> +
> +    public final class PersonReceiver implements PersonHandler {
> +        public List<Person> receivedPersons = new ArrayList<Person>();
> +
> +        @Override
> +        public void onPerson(Person person) {
> +            receivedPersons.add(person);
> +        }
> +    }
> +
> +    public interface PersonHandler {
> +        void onPerson(Person person);
> +    }
> +}
>
> Propchange: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperOneWayTest.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Added: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java
> URL: 
> http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java?rev=1188162&view=auto
> ==============================================================================
> --- 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java
>  (added)
> +++ 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java
>  Mon Oct 24 14:51:12 2011
> @@ -0,0 +1,61 @@
> +/**
> + * 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.component.bean.pojomessage;
> +
> +import junit.framework.Assert;
> +
> +import org.apache.camel.ContextTestSupport;
> +import org.apache.camel.Endpoint;
> +import org.apache.camel.builder.RouteBuilder;
> +import org.apache.camel.component.bean.PojoProxyHelper;
> +import org.junit.Test;
> +
> +public class PojoProxyHelperRequestReplyTest extends ContextTestSupport {
> +
> +    PersonReceiver receiver = new PersonReceiver();
> +
> +    @Test
> +    public void testRequestReply() throws Exception {
> +        Endpoint personEndpoint = context.getEndpoint("direct:person");
> +        Person person = new Person("Chris");
> +        PersonHandler sender = PojoProxyHelper.createProxy(personEndpoint, 
> PersonHandler.class);
> +
> +        Person resultPerson = sender.onPerson(person);
> +        Assert.assertEquals(person.getName() + "1", resultPerson.getName());
> +    }
> +
> +    @Override
> +    protected RouteBuilder createRouteBuilder() throws Exception {
> +        return new RouteBuilder() {
> +            public void configure() throws Exception {
> +                from("direct:person").bean(receiver);
> +            }
> +        };
> +    }
> +
> +    public final class PersonReceiver implements PersonHandler {
> +        @Override
> +        public Person onPerson(Person person) {
> +            return new Person(person.getName() + "1");
> +        }
> +    }
> +
> +    public interface PersonHandler {
> +        Person onPerson(Person person);
> +    }
> +
> +}
>
> Propchange: 
> camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/pojomessage/PojoProxyHelperRequestReplyTest.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
>
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cib...@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Reply via email to