1 Reply Latest reply on Dec 12, 2012 6:49 PM by Keith Babo

    Service Clustering with copies of DTOs

    Yusuf Bata Newbie

      Setting up a link from a SwitchYard service to another separately deployed SwitchYard service using the @Reference annotation works well when:

      • the DTO's are primitive types, or
      • The Provider service and Consumer service reference exactly the same jar containing the non-primitive DTO's, or
      • The Provider service and Consumer service have different copies of the DTO's but are deployed on different servers.

      When trying to link the Provider and Consumer services running on the same server with different copies of the DTO's, the following Transformation Error occurs:

      14:30:44,271 ERROR [org.apache.camel.processor.DefaultErrorHandler] (http--127.0.0.1-8080-2) Failed delivery for (MessageId: ID-FHLF3657051W7-59788-1355228590325-2-9 on ExchangeId: ID-FHLF3657051W7-59788-1355228590325-2-8). Exhausted after delivery attempt: 1 caught: org.switchyard.exception.SwitchYardException: Cannot convert from 'za.co.switchyard.services.SimpleInput' to 'za.co.switchyard.services.SimpleInput'.  No registered Transformer available for transforming from 'java:za.co.switchyard.services.SimpleInput' to 'java:za.co.switchyard.services.SimpleInput'.  A Transformer must be registered.: org.switchyard.exception.SwitchYardException: Cannot convert from 'za.co.switchyard.services.SimpleInput' to 'za.co.switchyard.services.SimpleInput'.  No registered Transformer available for transforming from 'java:za.co.switchyard.services.SimpleInput' to 'java:za.co.switchyard.services.SimpleInput'.  A Transformer must be registered.

                at org.switchyard.internal.DefaultMessage.getContent(DefaultMessage.java:108) [switchyard-runtime-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.Invocation.castArg(Invocation.java:91) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.Invocation.<init>(Invocation.java:58) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.BeanServiceMetadata.getInvocation(BeanServiceMetadata.java:90) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.ServiceProxyHandler.handle(ServiceProxyHandler.java:115) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.ServiceProxyHandler.handleMessage(ServiceProxyHandler.java:89) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.bus.camel.processors.ProviderProcessor.process(ProviderProcessor.java:39) [switchyard-bus-camel-0.6.0.Final.jar:0.6.0.Final]

                at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:91) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.Pipeline.process(Pipeline.java:117) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.Pipeline.process(Pipeline.java:80) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.switchyard.bus.camel.audit.FaultProcessor.process(FaultProcessor.java:58) [switchyard-bus-camel-0.6.0.Final.jar:0.6.0.Final]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:330) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:220) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.interceptor.DefaultChannel.process(DefaultChannel.java:303) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.Pipeline.process(Pipeline.java:117) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.Pipeline.process(Pipeline.java:80) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:122) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.RouteInflightRepositoryProcessor.processNext(RouteInflightRepositoryProcessor.java:48) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:61) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:150) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:86) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.processor.UnitOfWorkProducer.process(UnitOfWorkProducer.java:63) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:360) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:331) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:227) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:331) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:169) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:111) [camel-core-2.10.0.jar:2.10.0]

                at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:97) [camel-core-2.10.0.jar:2.10.0]

                at org.switchyard.bus.camel.ExchangeDispatcher.dispatch(ExchangeDispatcher.java:64) [switchyard-bus-camel-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.internal.ExchangeImpl.sendInternal(ExchangeImpl.java:199) [switchyard-runtime-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.internal.ExchangeImpl.send(ExchangeImpl.java:114) [switchyard-runtime-0.6.0.Final.jar:0.6.0.Final]

                at org.switchyard.component.bean.ClientProxyBean$ClientProxyInvocationHandler.invoke(ClientProxyBean.java:284) [switchyard-component-bean-0.6.0.Final.jar:0.6.0.Final]

                at $Proxy69.sayHello(Unknown Source)          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_33]

       

       

      This makes it difficult to isolate changes to the DTOs of one service from another service - backward compatibility cannot be achieved. Is this intended behaviour?

      As a workaround, I've manually used the remote binding to access the Provider Service from the Consumer Service. This approach however results in the loss of the runtime clustering facility (the endpoint URL is hard-coded in the Consumer Service).

      Any thoughts?

      Thanks!

      Yusuf.

        • 1. Re: Service Clustering with copies of DTOs
          Keith Babo Master

          Hey Yusuf,

           

          The three options you listed are what's available.  In-memory invocations between services will use the same class loader and you can't have two versions of the same class defined within the same loader.  The best way to decouple the two would be to introduce a serialization boundary which will allow the object to be loaded in two separate loaders between applications.  This is what you're getting with option 3 in your list.

           

          If you run into this issue a lot in your environment, it might be worth introducing an extensible canonical object model at the core of your architecture and then map specific DTO versions into that.  This way consumers and providers can have unique namespaces for their DTOs and they can evolve independently.  The two will be reconciled through declarative transformation to the canonical model and then the target model.  To support this in SwitchYard you will need support for transform chaining (e.g. A->B, B->C :: A->C), which should land in our 0.8 release.

           

          hth,

          keith