[ https://issues.apache.org/jira/browse/CAMEL-2026?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Claus Ibsen resolved CAMEL-2026. -------------------------------- Resolution: Won't Fix Fix Version/s: (was: Future) 2.8.0 Lets keep it as is > Enable async request-reply by enhancing the CamelInvocationHandler so that it > is serializable, so that camel-spring Proxies can be passed as callback > objects > ------------------------------------------------------------------------------------------------------------------------------------------------------------- > > Key: CAMEL-2026 > URL: https://issues.apache.org/jira/browse/CAMEL-2026 > Project: Camel > Issue Type: Improvement > Components: camel-core, camel-spring > Affects Versions: 2.0.0 > Reporter: Scott Clasen > Assignee: Claus Ibsen > Fix For: 2.8.0 > > Attachments: camel-2026.zip > > > With minor alteration, the CamelInvocationHandler could be made serializable, > and then camel-spring bean proxies could be passed as callback objects in > method calls on other camel-spring proxies...enabling async request-reply via > spring remoting. > I have achieved this by Wrapping the CamelInvocationHandler, subclassing the > CamelProxyFactoryBean, and by attaching a processor to routes that can > recieve BeanInvocations that have a callback object. Integrated into the > codebase, this could be much more straightforward, and not require a > processor be attached. > =================CamelInvocationHandlerWrapper > {code} > /** > * Serializable wrapper for Camel/Spring remoting proxies. > */ > public class CamelInvocationHandlerWrapper implements InvocationHandler, > Serializable { > /* > Findbugs will complain that inner dosent get set at deserialization time. > This is ok. > You need to have a CamelRemotingProcessor in your inbound camel route that > will reset the handler. > */ > private transient CamelInvocationHandler inner; > private String serviceUrl; > private static final long serialVersionUID = 7635312279175935612L; > /** > * Create a CamelInvocationHandlerWrapper. > * > * @param handler the handler to use in this VM. > * @param serviceUrl the serviceUrl to use to rebuild the > CamelInvocationHandler if we are serialized and used in a different VM. > */ > public CamelInvocationHandlerWrapper(CamelInvocationHandler handler, > String serviceUrl) { > this.inner = handler; > this.serviceUrl = serviceUrl; > } > /** > * {@inheritDoc} > */ > public Object invoke(Object proxy, Method method, Object[] args) throws > Throwable { > if (method.getDeclaringClass().equals(Object.class)) { > return method.invoke(this, args); > } else { > if (inner == null) { > throw new IllegalStateException("The inner > CamelInvocationHandler is null, perhaps there was no CamelRemotingProcessor > on your inbound route???"); > } else { > return inner.invoke(proxy, method, args); > } > } > } > /** > * Package Private so the CamelRemotingProcessor can rewire when we are > passed remotely. > * > * @param context the current camel context. > * @throws Exception if we cant build an endpoint for the service url or > create a producer. > */ > void rebuildInvocationHandler(CamelContext context) throws Exception { > Endpoint endpoint = CamelContextHelper.getMandatoryEndpoint(context, > serviceUrl); > Producer producer = endpoint.createProducer(); > producer.start(); > inner = new CamelInvocationHandler(endpoint, producer, new > MethodInfoCache(endpoint.getCamelContext())); > } > void setServiceUrl(String serviceUrl) { > this.serviceUrl = serviceUrl; > } > } > {code} > ================Proxy Factory > {code} > /** > * ProxyFactory that wraps a camel proxy in a serializable form. > */ > public class CamelProxyWrapperFactoryBean extends CamelProxyFactoryBean { > /** > * Override the CamelProxyFactoryBean to return a different proxy that > uses a CamelInvocationHandlerWrapper. > * > * @return a Proxy backed by a CamelInvocationHandlerWrapper for the > specified interface. > * @throws Exception if we cant create the proxy. > */ > @Override > public Object getObject() throws Exception { > Object proxy = super.getObject(); > CamelInvocationHandler handler = (CamelInvocationHandler) > Proxy.getInvocationHandler(proxy); > return Proxy.newProxyInstance(getObjectType().getClassLoader(), new > Class[]{getObjectType()}, new CamelInvocationHandlerWrapper(handler, > getServiceUrl())); > } > } > {code} > ========processor that "rewires" the transient CamelInvocationHandler by > using the service url > {code} > public class CamelRemotingProcessor implements Processor { > /** > * Rebuild the CamelInvocationHandler if we were passed a Proxy that has > a CamelInvocationHandlerWrapper as its handler. > * > * @param invocation the BeanInvocation whose args we check for the Proxy. > * @param context the current Camel Context. > * @throws Exception if something blows up. > */ > public void rewireProxy(BeanInvocation invocation, CamelContext context) > throws Exception { > Object[] args = invocation.getArgs(); > if (args != null) { > for (Object arg : args) { > if (Proxy.isProxyClass(arg.getClass())) { > InvocationHandler handler = > Proxy.getInvocationHandler(arg); > if (handler instanceof CamelInvocationHandlerWrapper) { > CamelInvocationHandlerWrapper wrapper = > (CamelInvocationHandlerWrapper) handler; > wrapper.rebuildInvocationHandler(context); > } > } > } > } > } > /** > * {@inheritDoc} > */ > public void process(Exchange exchange) throws Exception { > CamelContext context = exchange.getContext(); > BeanInvocation invocation = > exchange.getIn().getBody(BeanInvocation.class); > rewireProxy(invocation, context); > } > } > {code} -- This message is automatically generated by JIRA. For more information on JIRA, see: http://www.atlassian.com/software/jira