14 Replies Latest reply on Nov 2, 2010 2:56 PM by valig003

    How to create a consumer endpoint for a camel route using SOAP

    rkozura

      I have a question.  I am new to Camel.

       

      I have created a very simple camel route using the timer scheme to route a message from the timer to an nmr endpoint that accepts SOAP (jaxws )messages.  I now want to go a step further.

       

      I want to be able to expose an http endpoint on the ESB to accept SOAP messages and route the message to the nmr endpoint.  I have found a way to expose some sort of http endpoint using the jetty scheme, but when I send a SOAP request to the endpoint, I get the following error:

       

      ERROR:  'Source object passed to '''' has no contents.'

       

      This leads me to believe that jetty is not SOAP enabled.

       

      I'll stop pretending to know what I am talking about   Am I correct in using jetty as the http consumer?  Is there another scheme that could be used?  I find it strange that the jetty endpoint can have a different address as it sits in the ESB.

       

      Here is my camel route:

       

          <camel-osgi:camelContext xmlns="http://camel.apache.org/schema/spring">

              <route>

                  <from uri="jetty://http://localhost:8181/camel" />

                  <to uri="nmr:SOAPProxy"/>

              </route>

          </camel-osgi:camelContext>

        • 1. Re: How to create a consumer endpoint for a camel route using SOAP
          ffang

          Hi,

           

          This error means you need transform you message to some kind of Source(such as StringSource) before you send to nmr endpoint.

           

          Freeman

          • 2. Re: How to create a consumer endpoint for a camel route using SOAP
            rkozura

            Thank you!  I will try that soon and edit this post about it

            • 3. Re: How to create a consumer endpoint for a camel route using SOAP
              rkozura

              I transformed the message, but am still having problems.  The response is not going back to jetty.  The SOAP message does indeed go to correct location, that I am thankful for.

               

              Here is my route:

               

                  <camel-osgi:camelContext xmlns="http://camel.apache.org/schema/spring">

                      <route>

                          <from uri="jetty://http://localhost:8181/camel" />

                          <bean ref="myTransform" method="transform"/>

                          <to uri="nmr:SOAPProxy"/>

                      </route>

                  </camel-osgi:camelContext>

               

              Here is the transform method:

               

                  public Object transform(Source body) {

               

                      return body;

                  }

               

              A message is displayed by my web service stating the message was handled, but then I get the dreaded ArrayIndexOutOfBoundsException:

               

              java.lang.ArrayIndexOutOfBoundsException: 4096

                      at org.mortbay.io.ByteArrayBuffer.poke(ByteArrayBuffer.java:268)

                      at org.mortbay.io.AbstractBuffer.put(AbstractBuffer.java:456)

                      at org.mortbay.jetty.HttpFields$Field.put(HttpFields.java:1424)

                      at org.mortbay.jetty.HttpGenerator.completeHeader(HttpGenerator.java:523)

                      at org.mortbay.jetty.HttpConnection.commitResponse(HttpConnection.java:632)

                      at org.mortbay.jetty.HttpConnection$Output.flush(HttpConnection.java:1004)

                      at org.apache.camel.util.IOHelper.copy(IOHelper.java:101)

                      at org.apache.camel.util.IOHelper.copy(IOHelper.java:81)

               

              Thank you so much for your help so far!

               

              Edit:  Seems to be an issue with my Jetty version.  How do I update Jetty that is in FUSEESB?

               

              Edited by: rkozura on Aug 19, 2010 6:52 PM

               

              Edited by: rkozura on Aug 19, 2010 7:16 PM

              • 4. Re: How to create a consumer endpoint for a camel route using SOAP
                ffang

                Hi,

                 

                How about append option like exchangePattern=InOut to your jetty uri?

                 

                Freeman

                • 5. Re: How to create a consumer endpoint for a camel route using SOAP
                  rkozura

                  Like a game of poker:  No dice.

                  • 6. Re: How to create a consumer endpoint for a camel route using SOAP
                    rkozura

                    Is there any other endpoint I can expose besides Jetty?  All I want is an http endpoint consumer that uses camel.

                    • 7. Re: How to create a consumer endpoint for a camel route using SOAP
                      valig003

                      I have a similar problem and get the same error.  I have a CXF-based web service bundle that uses an OSGi bundle that provides database connectivity.  I want to use the Camel "throttle" pattern to avoid stressing the (production) database as a stop-gap. 

                       

                      Jetty/HTTP -> Camel Throttle -> CXF WebService (SOAP) -> OSGi Database Bundle -> JDBC Pool -> Database

                       

                      I wasn't able to get it to work until I added the "convertBodyTo" tag as suggested here.   With this tag, the service itself works great and throttles correctly, however I can no longer access the WSDL without the "*Source object passed to '''' has no contents*" error as reported in this post.  I assume this is because the body of a WSDL request is empty, but it seems like something the convertBodyTo should handle more elegantly.  I've tried putting error handling around it as well without any luck.  Any suggestions for how to get a WSDL operation to work without this error?  Like I said, the actual SOAP call to the service performs perfectly. 

                       

                      Here is part of my Spring setup:

                       

                      ...

                       

                           

                              <from uri="jetty:http://localhost:8181/cxf/EmailService" />

                              <convertBodyTo type="javax.xml.transform.stream.StreamSource" />

                              <throttle maximumRequestsPerPeriod="1" timePeriodMillis="10000">

                                <to uri="nmr:EmailService" />

                              </throttle>

                             

                       

                          <jaxws:endpoint id="emailWSDLService"

                                          implementor="#emailServiceBean"

                                          address="nmr:EmailService" />

                       

                      ...

                       

                      Edited by: valig003 on Oct 27, 2010 2:31 PM

                       

                      Edited by: valig003 on Oct 27, 2010 2:37 PM

                      • 8. Re: How to create a consumer endpoint for a camel route using SOAP
                        davsclaus

                        Try enabling stream caching instead of the convert body to.

                         

                        http://camel.apache.org/stream-caching.html

                        • 9. Re: How to create a consumer endpoint for a camel route using SOAP
                          valig003

                          Thanks for the suggestion, but this didn't affect the behavior.  Removing the "convertBodyTo" node caused errors regardless of stream-cache setting.  It also didn't change the behavior with both stream-cache AND "convertBodyTo". 

                           

                          Putting the "convertBodyTo" back allows SOAP calls with a message body to succeed, but WSDL calls to fail.

                           

                          StackTrace

                          org.apache.servicemix.nmr.api.ServiceMixException: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: Source object passed to '''' has no contents.      at org.apache.servicemix.cxf.transport.nmr.NMRDestination.process(NMRDestination.java:151)[278:org.apache.servicemix.cxf.transport.nmr:4.3.0.fuse-02-00]      at org.apache.servicemix.nmr.core.InternalEndpointWrapper.process(InternalEndpointWrapper.java:86)[81:org.apache.servicemix.nmr.core:1.3.0.fuse-01-00]      at org.apache.servicemix.nmr.core.ChannelImpl.process(ChannelImpl.java:255)[81:org.apache.servicemix.nmr.core:1.3.0.fuse-01-00]      at org.apache.servicemix.nmr.core.ChannelImpl$1.run(ChannelImpl.java:215)[81:org.apache.servicemix.nmr.core:1.3.0.fuse-01-00]      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)[:1.6.0_17]      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)[:1.6.0_17]      at java.lang.Thread.run(Thread.java:619)[:1.6.0_17] Caused by: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: Source object passed to '''' has no contents.

                               at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:720)[:1.6.0_17]

                               at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313)[:1.6.0_17]

                               at org.apache.servicemix.cxf.transport.nmr.NMRMessageHelper.convertMessageToInputStream(NMRMessageHelper.java:51)[278:org.apache.servicemix.cxf.transport.nmr:4.3.0.fuse-02-00]

                               at org.apache.servicemix.cxf.transport.nmr.NMRDestination.process(NMRDestination.java:127)[278:org.apache.servicemix.cxf.transport.nmr:4.3.0.fuse-02-00]

                               ... 6 more

                          Caused by: javax.xml.transform.TransformerException: Source object passed to '''' has no contents.

                               at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:668)[:1.6.0_17]

                               at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:708)[:1.6.0_17]

                               ... 9 more

                          • 10. Re: How to create a consumer endpoint for a camel route using SOAP
                            davsclaus

                            What do you mean by WSDL call?

                            • 11. Re: How to create a consumer endpoint for a camel route using SOAP
                              valig003

                              Sorry, I didn't want to completely hi-jack the original post here, but to answer your question:

                               

                              Without Camel, a CXF service is generally accessed at http://{some.host}/cxf/ServiceName.  The WSDL for that service is accessed at http://{some.host}/cxf/ServiceName?wsdl.  This is the endpoint that defines the service contract and would be given out to clients to let them call the service. 

                               

                              For my service, the following URLs work great until I add Camel:

                              http://localhost:8181/cxf/EmailService?wsdl

                              http://localhost:8181/cxf/EmailService  (for the SOAP call)

                               

                              Once the Camel throttle route listed above is added, I start getting the error "javax.xml.transform.TransformerException: Source object passed to '''' has no contents" for BOTH the WSDL and SOAP calls.  By adding the "convertBodyTo" call, the SOAP call works great and the throttling in Camel is awesome... but the call to retrieve the WSDL still comes back with the error, presumably because the body is empty in a WSDL call; seems like the transform that "convertBodyTo" uses can't handle an empty body. 

                               

                              I'm looking for a way to make both of these work for the Camel throttle - or a workaround if something is broken in Camel. 

                               

                              Thanks!

                              • 12. Re: How to create a consumer endpoint for a camel route using SOAP
                                valig003

                                I tried a different approach but *no longer get the Camel route to work*.  I tried removing the "nmr" references and instead hard coded three URI references... both the SOAP call and the WSDL worked and there was no need for the convertBodyTo call, but the Camel throttle no longer executed (no error, just didn't get called).

                                 

                                The confusing part is that there seem to be MANY ways to define a 'service' endpoint and they all have different behavior and visibility (osgi:service, cxf:cxfEndpoint, jaxws:endpoint, cxf:simple, camel:endpoint, ...).  Determining what protocols, URIs, and address settings to use is very fuzzy.  I haven't found a good example using Spring, CXF with the jaxws:endpoint tag, being called by Camel. 

                                 

                                For reference, here is my Spring config for deploying a CXF service via the jaxws endpoint... how do I get Camel to work with this service endpoint?

                                 

                                     

                                        <property name="testMode" value="$" />

                                    </bean>

                                 

                                    <jaxws:endpoint id="emailWSDLService"

                                                    implementor="#emailServiceBean"

                                                    address="http://localhost:8181/cxf/EmailService" />

                                • 13. Re: How to create a consumer endpoint for a camel route using SOAP
                                  njiang

                                  You may need to use other way to server the ?wsdl request, like using  to check the query string then send the request to cxf endpoint without use transformation.

                                  • 14. Re: How to create a consumer endpoint for a camel route using SOAP
                                    valig003

                                    Well, a little progress... the high level issue seems to be making Camel aware of CXF and allowing the WSDL call to pass through.  With some changes I've made, I now get a message related to "Can't find input stream in message".

                                     

                                    In researching this, there is an open Camel issue that was just addressed yesterday that seems to be the same issue: https://issues.apache.org/activemq/browse/CAMEL-3269

                                     

                                    I'm not sure how anyone could ever know all of the tweaks that are necessary to make this work, but here is my current spring file in hopes that it might help someone else (or that someone might see a mistake and set me straight!):

                                    -


                                     

                                            <property name="testMode" value="$" />

                                        </bean>

                                     

                                        <jaxws:endpoint id="emailWSDLService"

                                                        implementor="#emailServiceBean"

                                                        address="camel://direct:EmailService" />

                                                        <!-- URI: publishedEndpointUrl="http://$/EmailService" -->