14 Replies Latest reply on Jan 21, 2013 5:37 PM by kcbabo

    Does camel component route to a external reference?

    leandropantoja

      Hello,

       

       

      I've seen rules-camel-cbr and I try to implement the folowing scenario:

       

       

      I have two legacy Web services.

       

      I did a WSDL contract to expose it as as service using SOAP Binding and create a camel xml component.

       

      I would like to know if Ican use camel component to receive request and route to my legacy webservices based on XML content or I must use Riftsaw to do this.

       

       

      Thanks,

       

       

      Leandro.

        • 1. Re: Does camel component route to a external reference?
          kcbabo

          Check out camel-soap-proxy for an example of using Camel routing between two web services.  You can use Camel's XML or Java DSL for the implementation.  You could use Riftsaw as well - it really depends on what your requirements are and whether you need the advanced orchestration capabilities of BPEL.  My guess is that if you are looking at routing, a Camel route will be the best fit.

          • 2. Re: Does camel component route to a external reference?
            leandropantoja

            Hello Guys,

             

            I've done babo's recomendations. My project has no error, but doesn't work.

             

            I've create two switchYard projects:

             

            1 - Route1: Bean Service. It executes some code and return a response.

            2 - RouteService: It receives a request and routes (camel component - route.xml) to Route1 service.

             

             

            When I execute RouteService, it replys the same request XML.

             

             

            I have another questions:

             

            1 - I want to use XSL transformation to pass data from routeService to Route1. How can I do that on this projects?

            2 - If I create a new Route (Route2 for example), I woudl like to implement a CBR without drools. Does It possible?

             

            My projects are attached here.

             

            Thanks,

             

            Leandro.

            • 3. Re: Does camel component route to a external reference?
              leandropantoja

              Someone can help me?

               

              Thanks,

               

              Leandro

              • 4. Re: Does camel component route to a external reference?
                kcbabo

                I haven't had a chance to run you app yet, but looking at the config I can see that you need to specify the SOAP endpoint for the reference binding in route-service app.  This can come from one of two places:

                 

                1) By default, the value from soap:address in the WSDL will be used.  Looking at your switchyard.xml, the binding.soap for your reference binding points to Route1.wsdl.  Looking inside that, the soap:address is "REPLACE_WITH_ACTUAL_URL".

                2) You can override the value specified in Route1.wsdl by using the "endpointAddress" config element in your reference binding.  More detail on that can be found in the SOAP binding docs.

                 

                Do you see an error or stack trace in the server log when a message is sent?  What's happening here is that the message is failing in the reference binding in the route-service app, but it is not being returned as a fault due to this issue:

                 

                https://issues.jboss.org/browse/SWITCHYARD-1247

                • 5. Re: Does camel component route to a external reference?
                  kcbabo

                  1 - I want to use XSL transformation to pass data from routeService to Route1. How can I do that on this projects?

                   

                  What are you trying to do with the transformation?  There are a number of possibilities.  Declarative transformation in SwitchYard is what you get with the transform.xxx definitions in switchyard.xml.  These help resolve data format/representation incompatibilities between services.  So if one service speaks XML and the other speaks Java, then you can use a transformer to resolve that independent of the service implementations. Same concept applies if different XML types are being used.  The thing to keep in mind is that this is all driven off of the service contract (interface.java, interface.wsdl, ...).

                   

                  In addition to declarative transformation, you could just code the transformation logic directly into your service implementation.  This would usually be used in cases where the transformation contains business logic (e.g. enrichment) or is directly related to routing.  In this case, you can do something like invoke an xslt transform using the XSLT component within a Camel route.

                   

                  2 - If I create a new Route (Route2 for example), I woudl like to implement a CBR without drools. Does It possible?

                   

                  Yes.  Drools is just one example of performing an evaluation on a message payload and routing based on the result.  You can use the CBR EIP support in Camel directly as well:

                   

                  http://camel.apache.org/content-based-router.html

                  • 6. Re: Does camel component route to a external reference?
                    leandropantoja

                    Hi Keith,

                     

                    My proxy service (route-service) :

                     

                    <sca:service name="RouteServiceProxy" promote="Route/RouteService_ptt">

                          <sca:interface.wsdl interface="META-INF/RouteService.wsdl#wsdl.porttype(RouteService_ptt)"/>

                          <soap:binding.soap>

                            <soap:wsdl>META-INF/RouteService.wsdl</soap:wsdl>

                            <soap:wsdlPort>RouteServicePort</soap:wsdlPort>

                            <soap:contextPath>route-service</soap:contextPath>

                          </soap:binding.soap>

                        </sca:service>

                     

                    It has a WSDL with  <soap:address location="REPLACE_WITH_ACTUAL_URL"/>. In this case, location is replaced at runtime. Right?

                     

                    Is has a reference (route-1).

                     

                    <sca:service name="RouteServiceProxy" promote="Route/RouteService_ptt">

                          <sca:interface.wsdl interface="META-INF/RouteService.wsdl#wsdl.porttype(RouteService_ptt)"/>

                          <soap:binding.soap>

                            <soap:wsdl>META-INF/RouteService.wsdl</soap:wsdl>

                            <soap:wsdlPort>RouteServicePort</soap:wsdlPort>

                            <soap:contextPath>route-service</soap:contextPath>

                          </soap:binding.soap>

                        </sca:service>

                     

                     

                     

                    The WSDL document has  <soap:address location="http://localhost:8080/route-1/Route1"/>

                     

                    No error message ou warning occours when I execute service. This message appears:

                     

                    11:27:51,557 INFO  [route1] (http-localhost-127.0.0.1-8080-1) RouteService_ptt - message received: <xsd:routeServiceRequest xmlns:xsd="http://www.grupomult.com.br/soa/switchyard/RouteService/xsd">

                             <xsd:id>1</xsd:id>

                          </xsd:routeServiceRequest>

                     

                     

                    Thanks.


                     



                    • 7. Re: Does camel component route to a external reference?
                      leandropantoja

                      About <soap:address location="REPLACE_WITH_ACTUAL_URL"/>, I've changed by location="http://localhost:8080/route-service/RouteService" and doesnt work.

                       

                       

                      About transformation, my integration scenario is very simple:

                       

                      1 proxy service routing to a external reference:

                       

                      2 WSDL and 2 XML different schemas. No Java code.

                       

                      I know about XSL, xQuery and other transformations technologies. What I can't see is where I must put the transformations files, or reference them, in this case.

                       

                      In another SOA platforms I can do this easily.

                       

                      Best Regards,

                      • 8. Re: Does camel component route to a external reference?
                        kcbabo

                        I must have been looking at the WSDL in the route-1 project as I missed the soap:address definition in the route-service copy of WSDL.  Can you enable TRACE logging for "org.switchyard.component.soap" in your AS 7 config (standalone.xml)?  That will dump all SOAP traffic so that we can see how far this is going.

                        • 9. Re: Does camel component route to a external reference?
                          kcbabo

                          Put the transformation files in your app where you like.  In your application project, something like "src/main/resources/xslt/mytransform.xsl" would be an example.  At this point, you can decide between declarative and procedural transformation.  Declarative transformation would kick in if the message types defined in the WSDLs used for the component reference and composite reference are different.  In other words, declarative transformation kicks in when we can detect that the data types are different in the runtime.  In your application, the component reference (composite/component/reference) "Route1ExternalReference" uses Route1.wsdl as the contract.  This is basically the consumer contract for the service.  The reference binding in your application (composite/reference) also uses Route1.wsdl, which is equivalent to the provider's contract.  The runtime believes that the data types are the same, so we will not invoke a transformation independently.  One way to handle this would be to have different types defined in your WSDL and a transform.xslt defined in your switchyard.xml which has the "from" and "to" which corresponds to these types.  The runtime will then automatically invoke this transformation any type Route1 is invoked from RouteService.


                          The other way to go would be to explicitly call the XSLT transform from your Camel route like this:

                           

                          <route xmlns="http://camel.apache.org/schema/spring">

                            <from uri="switchyard://RouteService_ptt"/>

                            <log message="RouteService_ptt - message received: ${body}"/>

                             <to uri="xslt:xslt/mytransform.xsl"/>

                            <to uri="switchyard://Route1ExternalReference"/>

                          </route>

                           

                          This option would be the traditional procedural option for transformation.  You can choose either one based on your own preference.

                          • 10. Re: Does camel component route to a external reference?
                            leandropantoja

                            Hi Keith,

                             

                            I did what you said (I've created a tranformation file, etc...), but the following error occours:

                             

                            17:26:48,956 WARN  [org.switchyard.transform.TransformSequence] (http-localhost-127.0.0.1-8080-2) Transformer 'org.switchyard.transform.TransformerUtil$1' returned a null transformation result.  Check input payload matches requirements of the Transformer implementation.

                            17:26:48,960 ERROR [org.jboss.ws.common.invocation.InvocationHandlerJAXWS] (http-localhost-127.0.0.1-8080-2) Method invocation failed with exception: null: java.lang.reflect.InvocationTargetException

                                      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [classes.jar:1.6.0_37]

                                      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [classes.jar:1.6.0_37]

                                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [classes.jar:1.6.0_37]

                                      at java.lang.reflect.Method.invoke(Method.java:597) [classes.jar:1.6.0_37]

                                      at org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke(AbstractInvocationHandlerJSE.java:111)

                                      at org.jboss.wsf.stack.cxf.JBossWSInvoker._invokeInternal(JBossWSInvoker.java:181)

                                      at org.jboss.wsf.stack.cxf.JBossWSInvoker.invoke(JBossWSInvoker.java:127)

                                      at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)

                                      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) [classes.jar:1.6.0_37]

                                      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) [classes.jar:1.6.0_37]

                                      at java.util.concurrent.FutureTask.run(FutureTask.java:138) [classes.jar:1.6.0_37]

                                      at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)

                                      at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)

                                      at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)

                                      at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)

                                      at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:207)

                                      at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:91)

                                      at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:169)

                                      at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:87)

                                      at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:185)

                                      at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:108)

                                      at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

                                      at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:135)

                                      at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140) [jbossws-spi-2.0.3.GA.jar:2.0.3.GA]

                                      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

                                      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)

                                      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)

                                      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)

                                      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)

                                      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)

                                      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

                                      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

                                      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)

                                      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)

                                      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671)

                                      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930)

                                      at java.lang.Thread.run(Thread.java:680) [classes.jar:1.6.0_37]

                            Caused by: org.switchyard.exception.SwitchYardException: Transformations not applied.  Required payload type of 'java:java.lang.String'.  Actual payload type is '{http://www.grupomult.com.br/soa/switchyard/Route1/xsd}route1Request'.  You must define and register a Transformer to transform between these types.

                                      at org.switchyard.component.soap.InboundHandler.invoke(InboundHandler.java:223) [switchyard-component-soap-0.6.0.Final.jar:0.6.0.Final]

                                      at org.switchyard.component.soap.endpoint.BaseWebService.invoke(BaseWebService.java:113) [switchyard-component-soap-0.6.0.Final.jar:0.6.0.Final]

                                      at org.switchyard.component.soap.endpoint.BaseWebService.invoke(BaseWebService.java:43) [switchyard-component-soap-0.6.0.Final.jar:0.6.0.Final]

                                      ... 37 more

                             

                            I project route-service is on attachments.

                             

                             

                            Thanks.


                             


                            • 11. Re: Does camel component route to a external reference?
                              rcernich

                              Hey Leandro,

                               

                              This is just a shot in the dark, but looking at your route and your switchyard configuration, it looks like everything would work if you removed the "to(xslt:...)" line from your route definition.

                               

                              Best,

                              Rob

                              • 12. Re: Does camel component route to a external reference?
                                leandropantoja

                                Hi Rob,

                                 

                                If I remove the line, the transformation data beetwen proxy service and service reference doesnt work and I back to initial state where I send a request and receive the same data on response.

                                 

                                 

                                Thanks,

                                 

                                Leandro.

                                • 13. Re: Does camel component route to a external reference?
                                  kcbabo

                                  I see that you have transformations defined in the switchyard.xml and in your camel route.  For this case, you don't need both.  It's either or.  I'll take a look at the app and see what's up.

                                  • 14. Re: Does camel component route to a external reference?
                                    kcbabo

                                    Turns out there were multiple layers to this onion as evidenced by the amount of crying I did in the past 30 minutes trying to debug it.  A few things to point out:

                                     

                                    1) I want to reiterate that you only need the Camel xslt: transformation based on the current application's structure.  You can remove the transform.xslt definitions in your switchyard.xml since the contract types used by the component and composite reference are the same.

                                     

                                    2) I couldn't get your app to deploy as is.  Looks like the style attribute was specified at the operation level instead of the binding level in the WSDL. This is perfectly legal, but did expose a bug in SY.  I filed a JIRA to fix it in 0.8:

                                    https://issues.jboss.org/browse/SWITCHYARD-1258

                                     

                                    3) The logic in your transformation code (Route1Transform.java) to pull the id element appears to be off and it was returning null.  I just hard-coded a return value to test and it worked fine. The underlying issue is that our transformation logic assumes a null response indicates no transformation was applied.  It does provide this rather cryptic error message in the log, but it's easy to miss inside the other error info:

                                    17:09:15,434 WARN  [org.switchyard.transform.TransformSequence] (http--127.0.0.1-8080-2) Transformer 'org.switchyard.transform.TransformerUtil$1' returned a null transformation result.  Check input payload matches requirements of the Transformer implementation.
                                    

                                     

                                    I'm not happy with the above behavior, so I've logged another JIRA to fix it:

                                    https://issues.jboss.org/browse/SWITCHYARD-1259

                                     

                                    In summary, the root cause of your problem was that we interpret a null return from a transformer to be a transformation failure.  This will be fixed.  In the meantime, I have attached a zip of your two projects with a hard-coded return value from the transfomer in the route-1 application.  The two apps work in my environment with this change.