Forum Home » Fuse Distributions » Fuse ESB

Thread: Camel Router to a Web Service (InOut)

 

Permlink Replies: 30 - Last Post: May 3, 2010 3:51 PM Last Post By: fsalceda
awhelan

Posts: 14
Registered: 05/21/09
Camel Router to a Web Service (InOut)
Posted: Mar 19, 2010 9:07 PM
  Click to reply to this thread Reply
Hello All.

Basically what I have working is simply a service engine endpoint that exposes a web service:

<cxfse:endpoint id="customerServiceSE"
service="example:customerService"
endpoint="endpoint">
<cxfse:pojo>
<bean class="com.srcinc.purchase_order.customer.service.CustomerServicePortTypeImpl">
<constructor-arg>
<ref bean="entityManagerFactory"/>
</constructor-arg>
</bean>
</cxfse:pojo>
</cxfse:endpoint>

and I have a binding component that exposes it outside of the ESB

<cxfbc:consumer wsdl="classpath:wsdl/CustomerService.wsdl"
targetService="example:customerService"
targetEndpoint="endpoint"/>
<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />

I need to stick a camel router in between so that when calling it from a client
I can route the incoming call to the web service service engine (customerServiceSE)
end point but also route that same input off to other places. I want the web service
call to return output also (InOut).

I'm stuck as to how I do this, being a Fuse newby and all.

Basically I want the RouteBuilder DSL to do something like

public void configure() {
from("binding component interface").to("service engine web service endpoint")
.to("somewhere else-a file, another web service, what ever");
}
I'm not really sure how to go about doing this. Is there a way to
add a router to the binding component? Does this even make sense?
I am using Fuse 4.2 and just deploying
the service engine and binding component as OSGI bundles. Any suggestions or help would be
appreciated.

ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Mar 20, 2010 2:23 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi,

Yeah, you can do it with deploying DSL in servicemix-caml component, which support using JBI in camel, take a look at [1], and more importantly, Using JBI in Camel[2]

[1]http://servicemix.apache.org/servicemix-camel.html
[2]http://camel.apache.org/jbi.html

Freeman

awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Mar 20, 2010 11:47 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Thanks freeman.

I've got the binding component and service engine installed as OSGI bundles with no service assembly involved.

Does it make sense to do this (JBI Camel) with ServiceMix installing it as an OSGI bundle? Thats kind of where I'm crashing.

thanks
-Andy
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Mar 20, 2010 11:52 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
I guess my question would be better stated by asking if it is common
to call jbi endpoints from within components deployed as OSGI bundles like this? Does it matter(not using a service assembly)?

from("jbi:endpoint:http://foo.bar.org/MyService/MyEndpoint")

thanks
-Andy
ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Mar 21, 2010 6:57 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi,

Yeah, it's ok to call jbi endpoints from bundle.

Freeman
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Mar 23, 2010 4:13 PM   in response to: ffang in response to: ffang
  Click to reply to this thread Reply
I got something work with the JBI stuff to a point but I'm still crashing on something.

I have the following configuration:
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">
	
	<camel:jmxAgent id="agent" disabled="true" />
		<camel:routeBuilder ref="fileRoute" />
	</camel:camelContext>
 
 
	<bean id="fileRoute"
		class="com.srcinc.purchase_order.router.PurchaseOrderRouter">
		<property name="toUri" value="file:C:/EW/webinar/outgoing" />
	</bean>


And the following DSL:
public void configure() {
    	 LOG.info("PurchaseOrderRouter configure");
    
    	 
    	 from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint")
    	 .convertBodyTo(String.class)
    	 .to(toUri);
    	 
    }

The "from" clause here contains a legitimate request-reply web service endpoint.
It properly takes the body of the message, converts it to a string and sends it where
I want but the original web service call gets hijacked and doesn't complete. I want
the original web service call to go on its way and complete, I just want to be able to
capture the message contents as it passes through and do something else with that as well
{the .to(toUri) portion}. Is there an easy way to do this without generating and calling
proxy code here?

Edited by: awhelan on Mar 23, 2010 4:13 PM

Edited by: awhelan on Mar 23, 2010 4:17 PM
njiang

Posts: 572
Registered: 09/17/07
Re: Camel Router to a Web Service (InOut)
Posted: Mar 23, 2010 11:40 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Basically, you can use camel-jetty and camel-http to set up a http proxy in camel, then you can do what you want to do with the request and response message. I just assume the WebService can be access from the jbi endpoint that you showed to us in my example.
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">&#937;
    <route>	
        <from uri="jetty://http://YourProxyServicesAddress"/>
        <to uri="file:C:/EW/webinar/outgoing"/>
        <!-- you can also use the camel-http endpoint here -->
        <!-- to uri="http://TheWebServiceAddress" -->
        <to uri="jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint"/>
        <to uri="file:C:/EW/webinar/incomming"/>
    </route>
</camel:camelContext>
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Mar 24, 2010 9:03 PM   in response to: njiang in response to: njiang
  Click to reply to this thread Reply
The camel-jetty thing didn't seem to help, or maybe I'm not completely sure what to do with it. I did however find out the following. When I do the following with my router

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out")
.convertBodyTo(String.class)
.to(toUri);

The web service call actually completes the way I want it to but I have a different problem. The "mep=in-out" causes it to complete like I want it to but the rest of the command

.convertBodyTo(String.class)
.to(toUri);
to have no affect. Again, my web service call is a simple request/response type call. Maybe people aren't understanding this. I am calling it with SoapUI. I am calling a method that takes an argment and returns a response back to the SoapUI client. With
from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out") that part is working like I want it to. What isn't working is the

.convertBodyTo(String.class)
.to(toUri);
part. Besides just having the incoming call complete like it is I would like to be able to capture the SOAP content of the incoming call and send it somewhere else. Does anyone know what I can add to

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out") to make that work?
njiang

Posts: 572
Registered: 09/17/07
Re: Camel Router to a Web Service (InOut)
Posted: Mar 26, 2010 12:15 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
What kind of error do you have for the below part?
.convertBodyTo(String.class)
.to(toUri);
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Mar 26, 2010 2:54 PM   in response to: njiang in response to: njiang
  Click to reply to this thread Reply
Hi Willem,

.convertBodyTo(String.class)
.to(toUri);

isn't causing any errors, it's just not doing anything. It doesn't seem to have any effect when attached to

from ("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out")

My web service call simply takes some information as an argument(the request portion of the web service call) and adds it to a database. I want to be able to call my web service from a client, have it add the argument data to the database like it does, but I want to grab the SOAP request data within the Camel router and do something else with it also.

Is there an easy way to grab the SOAP request data from

from ("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out")

while it's passing through using Camel, but still have the web service complete?

The web service is implemented as a service engine, exposed through a binding component at the endpoint "jbi:endpoint:http://purchase_order.srcinc.com/customerService". The "from" statement above allows the web service call to complete like I want but I'm looking for a way to grab the request data from the SOAP envelope also.

I'm hoping for an easy way?

The hard way would be something like generating client proxy code from the WSDL, and doing something like the following
from ("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint").Process();

where I have to consume the request, and use the client stubs generated from the WSDL call the web service again in the Process implementation just to get access the request portion of the SOAP call and then return the SOAP response to the user.

Do you have any advice? Any help is greatly appreciated.
thanks!
dkruitbosch

Posts: 27
Registered: 08/20/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 7, 2010 8:38 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi Andy,

If I understand correctly, you want to send a SOAP request through the ESB in order to send it of to it's original/final destination and send the same request to another destination in order to proces that "copied" request independently?

If so why not use a wiretap in your camel route. I had a similar issue, and the wiretap (available since camel 2.x) solved it for me (at least for the requests). And if you need to "tap" the responses, there's a "onCompletion" handler in camel 2.x

Look at this post in the camel-users mailing list and maybe it'll solve your issue :)

http://old.nabble.com/Wiretap-filter-ts27527108.html#a27528824

Regards,

Danny

Edited by: dkruitbosch on Apr 7, 2010 8:38 PM
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel wireTap router with InOut WebService
Posted: Apr 12, 2010 1:37 PM   in response to: dkruitbosch in response to: dkruitbosch
  Click to reply to this thread Reply
Hi Clause

Actually there is no other route (SMX EIP) or anything.

I have a service engine enpoint configured as follows:
<cxfse:endpoint id="customerServiceSE"
service="example:customerService"
endpoint="endpoint">
<cxfse:pojo>
<bean class="com.srcinc.purchase_order.customer.service.CustomerServicePortTypeImpl">
<constructor-arg>
<ref bean="entityManagerFactory"/>
</constructor-arg>
</bean>
</cxfse:pojo>
</cxfse:endpoint>

There is also a binding component to expose it to the outside world.

The following Camel "from" acts as a consumer for the above web service.
from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out")

As far as I know this is where I recieve the message.
If I add .ConvertBody(String.class).to("file:C:/out.txt") to the above from clause it writes the web service input to the the file C:/out.txt. The web service never completes though.

I want to wiretap it so it writes the file out as it does above
but I'd like the web service to complete.

For the following:
from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out").wireTap("file:C:/out.txt");

The web service is consumed, the call actually completes, returning its output to the client but the file C:\out.txt is not created.

Any ideas on what I'm missing? Do I really need some other route (SMX EIP???) in order to acomplish this?

awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 12, 2010 1:47 PM   in response to: dkruitbosch in response to: dkruitbosch
  Click to reply to this thread Reply
Sorry Danny and other members. I actually have two similar threads going. I decided the Mediator forum was probably more appropriate for wiretap questions so decided to try my luck there. When trying to respond to responses on that I accidently pasted it into this thread.

Actually, thanks Danny. I think the wiretap is exactly what I need.

I'm just trying to figure out how to get the following:

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out").wireTap("file:C/out.txt");

actually writing out.txt. The from clause is successfully consuming the web service and returning a response to the client, but the web service request isn't being written to C:\out.txt. Any tips or things to try will be appreciated.
-Andy
davsclaus

Posts: 1,893
Registered: 10/14/08
Re: Camel Router to a Web Service (InOut)
Posted: Apr 12, 2010 1:49 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Looks like you file path is wrong. You need C:/out. And maybe also try without a C letter, but just: /out
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 12, 2010 5:37 PM   in response to: davsclaus in response to: davsclaus
  Click to reply to this thread Reply
Hi Clause,

The file path text was just a typo. It still doesn't work. Let me run something else past yah's though.

If I have the "?mep=in-out" at the end of the endpoint in the from clause, the web service completes, but the wiretap doesn't work (no file is written).

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint?mep=in-out")
.wireTap("file:C:/EW/webinar/customer/soap/?fileName=report.txt")
;

If on the other hand I remove the "?mep=in-out" from the end of the endpoint in the from statement, the web service doesn't complete but the request is writtten to the file (half of what I want).

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint")
.wireTap("file:C:/EW/webinar/customer/soap/?fileName=report.txt")
;
Does this ring any bells? Again, I want the web service to complete and I want the file written to.
Thanks
davsclaus

Posts: 1,893
Registered: 10/14/08
Re: Camel Router to a Web Service (InOut)
Posted: Apr 14, 2010 4:12 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
I will let on of the SMX people take a look at this. For me the mep option at the consumer level doens't make sense. Webservices is by nature request/response based.

If you do this in pure Camel, eg then that would be easy:
from("cxf:bean:MyWebService").wireTap("tapMe").process(SET SOME REPLY HERE)
gertv

Posts: 167
Registered: 06/18/08
Re: Camel Router to a Web Service (InOut)
Posted: Apr 20, 2010 10:17 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
L.S.,

If the JBI MessageExchange is being sent to this route, it will only do the wiretap that is inside the route. If you want to create a route with a wiretap before the service, you should expose that as another endpoint, e.g.

from("jbi:endpoint:http://purchase_order.srcinc.com/customerService/tapped")
.wireTap("file:C:/EW/webinar/customer/soap/?fileName=report.txt")
.to("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint");

You can now configure your CXF consumer to target the 'tapped' service, which will do the wiretap and forward to the original endpoint.

Regards,

Gert
dkruitbosch

Posts: 27
Registered: 08/20/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 14, 2010 11:29 AM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi Andy,

Glad to be of help. I'm just starting to discover the power of fuse esb and I have loads of fun experimenting with it....

You can add a trace="true" into the camelContext in your spring config
e.g. <osgi-camel:camelContext xmlns="http://activemq.apache.org/camel/schema/spring" trace="true">

Then on the smx console you can see what's happening with the log commands.
This helps me a lot when solving these kinds of issues.

Reqards,

Danny
dkruitbosch

Posts: 27
Registered: 08/20/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 15, 2010 12:41 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi Andy,

Playing around with smx it just hit me, and I have a solution to you're issue
I have a similar setup, and I've changed it to see if I could reproduce you're issue.

The setup I have:

soap client -> soap consumer bc -> camel router -> soap provider bc -> real service

The problem lies in you're camel route. If you define a jbi endpoint in the from statement of your camel route, this becomes an exposed endpoint in the nmr. Make sure this differs from your consumer bc endpoint. Next adjust your consumer config to specify the camel jbi endpoint as it's target. And of course the camel route should point to your service engine endpoint in the "to" statement.

What happens in your current config, is that you have to similar endpoints defined (consumer bc and camel) and since the camel endpoint is not exposed "outside" the esb, you'll always bypass it.
Also there is no need to convert the soap body before the wiretap. The wiretap will convert to string automatically if you specify a file uri.

Hope this is clear and helps, if not send me a PM and I'll try to help some more.

Regards,

Danny

P.S. See http://camel.apache.org/jbi.html for more info on this ;)

Edited by: dkruitbosch on Apr 15, 2010 12:42 PM
awhelan

Posts: 14
Registered: 05/21/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 20, 2010 1:14 PM   in response to: dkruitbosch in response to: dkruitbosch
  Click to reply to this thread Reply
Success.
Actually the following does what I want it to.

from("jbi:endpoint:http://purchase_order.srcinc.com/routeService/CustomerServiceRouting")
.wireTap("file:C:/EW/webinar/customer/soap/?fileName=report.txt")
.to("jbi:endpoint:http://purchase_order.srcinc.com/customerService/endpoint")
    	 ;


Where
{http://purchase_order.srcinc.com}/routeService
is my routing service
CustomerServiceRouting is the routing endpoint

So the BC is
<cxfbc:consumer wsdl="classpath:wsdl/CustomerService.wsdl"
targetService="http://purchase_order.srcinc.com:routeService"
targetEndpoint="routeEndpoint"/>

{http://purchase_order.srcinc.com}/CustomerService
is my service engine service
and "endpoint" is my service engine endpoint.
The service engine doesn't need to be exposed to the outside world. Just needs to be available within the ESB.

Thanks to Danny for helping plug the final missing pieces in.
Thanks to Willem, Freeman, and Clause for help other help along the way. I couldn't have gotten this far without you guys.
fsalceda

Posts: 79
Registered: 01/29/10
Re: Camel Router to a Web Service (InOut)
Posted: Apr 29, 2010 2:25 PM   in response to: awhelan in response to: awhelan
  Click to reply to this thread Reply
Hi there, how did you manage to get a portion of the body, parsed it or made the parameters mapping from one webservice message to the other one?
My original webservice operation and request differs from the final webservice operation and request I want to invoke. So I have to map the operation and parameters. I already have: Cxf-consumer-BC -> CamelRouter -> Cxf-provider-BC -> WebService. The routing flow works fine because Its logging where the router is calling. But when the provider receives the original message it crashes:

{{{
16:19:40,676 | INFO | x-camel-thread-4 | route14 | rg.apache.camel.processor.Logger 212 | ************ TO ADD
16:19:40,688 | ERROR | -cxf-bc-thread-5 | CxfBcComponent | icemix.common.AsyncBaseLifeCycle 480 | Error processing exchange org.apache.servicemix.jbi.runtime.impl.InOutImpl@ef59ba
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
16:19:40,689 | ERROR | x-camel-thread-4 | DefaultErrorHandler | rg.apache.camel.processor.Logger 248 | Failed delivery for exchangeId: 5cffe8b6-a251-47fd-a0a4-edb9d6034f63. Exhausted after delivery attempt: 1 caught: java.lang.NullPointerException
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
16:19:40,690 | WARN | 4@qtp-28993516-1 | PhaseInterceptorChain | ache.cxf.common.logging.LogUtils 361 | Interceptor for {http://routing.examples.andago.com}routingExampleService#{http://routing.examples.andago.com}routing has thrown exception, unwinding now
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiPostInvokerInterceptor.handleMessage(CxfBcConsumer.java:866)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:109)
at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiChainInitiationObserver.onMessage(CxfBcConsumer.java:675)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:312)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:276)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerList.handle(HandlerList.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

}}}

Should I set the webservice operation I want to call in the provider binding component? Because the ws operation namespace and name I call in the consumer is not the same I want to call in the provider binding component. Or Should I do something like a message transform before calling the provider?

Hope somebody could help me.

Thanks.
ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Apr 29, 2010 2:52 PM   in response to: fsalceda in response to: fsalceda
  Click to reply to this thread Reply
Hi,

You must ensure the message payload meet the requirement as what cxf bc provider servicemodel (build from wsdl) expected before you send it to cxf bc provider endpoint.
So I believe what you need is pretty much a transformer, I guess you can also do transform in camel router, to make the message payload valid for cxf bc provider.

Freeman
dkruitbosch

Posts: 27
Registered: 08/20/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 29, 2010 2:56 PM   in response to: fsalceda in response to: fsalceda
  Click to reply to this thread Reply
Hi,

In your camel router you can use XSLT transformations to transform the soap message to the new request. What I usually do is transform the whole soap message, so you can leave the soap headers intact of change them (so set the useSOAPEnvelope on true.

your route will look something like this:

<route>
<from uri="jbi:yourcamelrouteendpoint/>
<to uri="xslt:sometemplate.xsl/>
<to uri="jbi:yourproviderbc/>
</route>

Look at the camel docs on how to use the xslt component.
As an alternative you can create a bean to do the transform, but I usually find xslt or xquery easier when handling XML (might be because I'm not a java programmer ;) )

Danny
fsalceda

Posts: 79
Registered: 01/29/10
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 8:11 AM   in response to: dkruitbosch in response to: dkruitbosch
  Click to reply to this thread Reply
Hi, I did what you advised me. I activated the soap envelope and used xslt to do the message transformation. But I'm still doing something wrong because now I get this exception when I call it.

09:51:03,431 | INFO | x-camel-thread-4 | route4 | rg.apache.camel.processor.Logger 212 | ************ TO ADD
09:51:03,433 | INFO | x-camel-thread-4 | route2plus-xslt | rg.apache.camel.processor.Logger 88 | Exchange
09:51:03,435 | ERROR | -cxf-bc-thread-3 | CxfBcComponent | icemix.common.AsyncBaseLifeCycle 480 | Error processing exchange org.apache.servicemix.jbi.runtime.impl.InOutImpl@7210ec
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
09:51:03,436 | ERROR | x-camel-thread-4 | DefaultErrorHandler | rg.apache.camel.processor.Logger 248 | Failed delivery for exchangeId: 350d178e-77b9-48a4-a360-fd2989d3a1be. Exhausted after delivery attempt: 1 caught: java.lang.NullPointerException
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
09:51:03,440 | WARN | 99@qtp-1930252-1 | PhaseInterceptorChain | ache.cxf.common.logging.LogUtils 361 | Interceptor for {http://routing.examples.andago.com}routingExampleService#{http://routing.examples.andago.com}routing has thrown exception, unwinding now
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiPostInvokerInterceptor.handleMessage(CxfBcConsumer.java:859)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:109)
at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiChainInitiationObserver.onMessage(CxfBcConsumer.java:675)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:312)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:276)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerList.handle(HandlerList.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)


My cxf consumer configuration:

<cxfbc:consumer wsdl="classpath:wsdl/RoutingExampleService.wsdl"
targetService="routing:RoutingRouterService"
targetEndpoint="RoutingRouterEndpoint"
useJBIWrapper="false"
useSOAPEnvelope="true"/>

My router configuration:

<osgi:camelContext id="router" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jbi:endpoint:http://routing.examples.andago.com/RoutingRouterService/RoutingRouterEndpoint" />
<choice>
<when>
<xpath>//xsd:operation = '0'</xpath>
<log message="************ TO ADD"/>
<to uri="xslt:xsl/route2plus.xsl"/>
<to uri="log:route2plus-xslt"/>
<to uri="jbi:service:http://toplus.examples.andago.com/ToPlus-Service" />
</when>
<when>
<xpath>//xsd:operation = '1'</xpath>
<log message="********* TO MULTIPLY"/>
<to uri="xslt:xsl/route2multiply.xsl"/>
<to uri="log:route2multiply-xslt"/>
<to uri="jbi:service:http://tomultiply.examples.andago.com/ToMultiply-Service" />
</when>
</choice>
</route>
</osgi:camelContext>

And my provider configuration:

<cxfbc:provider wsdl="classpath:wsdl/ToPlus-Service.wsdl"
locationURI="http://localhost:8888/axis2/services/ToPlus-Service"
service="toplus:ToPlus-Service"
endpoint="ServiceHttpSoap11Endpoint"
interfaceName="toplus:ToPlus-ServicePortType"
useJBIWrapper="false"
useSOAPEnvelope="true"/>

As you can see at the begining (the exception), the call is routed "TO ADD" service but after that I dont know if the message body is correct. Should the body be the whole message or is that part correct? I mean the cxf-consumer soap message is:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rout="http://routing.examples.andago.com" xmlns:xsd="http://beans.io.examples.andago.com/xsd">
<soapenv:Header/>
<soapenv:Body>
<rout:routingExampleIn>
<rout:opInfo>
<xsd:operation>0</xsd:operation>
<xsd:op1>2</xsd:op1>
<xsd:op2>5</xsd:op2>
</rout:opInfo>
</rout:routingExampleIn>
</soapenv:Body>
</soapenv:Envelope>

And the soap message that expects the final web service is:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:top="http://toplus.examples.andago.com">
<soapenv:Header/>
<soapenv:Body>
<top:toPlus>
<top:p1>2</top:p1>
<top:p2>5</top:p2>
</top:toPlus>
</soapenv:Body>
</soapenv:Envelope>

And you can see in the exception stacktrace:

Exchange[BodyType:String, Body:<?xml version="1.0" encoding="UTF-8"?><soap ...

Is that what the cxf-provider is waiting for?

Regards & Thx again.

Edited by: fsalceda on Apr 30, 2010 8:21 AM

ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 9:08 AM   in response to: fsalceda in response to: fsalceda
  Click to reply to this thread Reply
Hi,

What cxf bc provider expect is totally depend on the wsdl used for cxf bc provider.

So I can't tell so much before I see the wsdl, also could you please post the message send to cxf bc provider endpoint?

If you enable debug log level, you will see all messages going through NMR.

Freeman
dkruitbosch

Posts: 27
Registered: 08/20/09
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 10:09 AM   in response to: ffang in response to: ffang
  Click to reply to this thread Reply
Also, putting trace="true" on the <osgi:camelContext trace="true"> helps a lot in the debugging.

Can you also post the xslt files? Maybe there's something in the xslt that doesn't create the right message for the provider-bc.

Best way to test this is by using an xslt editor and test the transformations outside your esb config. Just create the input file and the xslt and see if the transformation result is the expected input for your provider-bc (including the soap envelope).

Danny
fsalceda

Posts: 79
Registered: 01/29/10
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 10:30 AM   in response to: ffang in response to: ffang
  Click to reply to this thread Reply
In my previous post you can see what my final web service expects to receive I copied the soap messages from soapui, and the soap message that my cxf-consumer is receiving. In addition I set up "DEBUG" log level and I saw where it actually is crashing:

12:12:14,532 | DEBUG | -cxf-bc-thread-2 | NMR | .servicemix.nmr.core.ChannelImpl 274 | Channel org.apache.servicemix.nmr.core.ChannelImpl@1fee2db dispatching exchange: [
id: 7e71834a-b5ab-4076-a903-b7722bfc5afa
mep: InOut
status: Error
role: Provider
target: PropertyMatchingReference{SERVICE_NAME={http://toplus.examples.andago.com}ToPlus-Service}
operation: {http://routing.examples.andago.com}routing
properties: [
javax.jbi.ServiceEndpoint = org.apache.servicemix.jbi.runtime.impl.ServiceEndpointImpl@1c4cc17
javax.jbi.messaging.MessageExchange = org.apache.servicemix.jbi.runtime.impl.InOutImpl@9238ca
javax.jbi.messaging.sendSync = <null>
javax.jbi.servicedesc.ServiceEndpoint = org.apache.servicemix.jbi.runtime.impl.EndpointImpl@a21de3
CamelToEndpoint = service:http://toplus.examples.andago.com/ToPlus-Service
JbiOperation = {http://routing.examples.andago.com}routing
javax.jbi.ServiceName = {http://toplus.examples.andago.com}ToPlus-Service
org.apache.servicemix.correlationId = 5b66de36-0b3b-4bce-8bdc-520ada159bd3
javax.jbi.transaction.jta = <null>
javax.jbi.InterfaceName = <null>
org.apache.servicemix.senderEndpoint = {http://camel.apache.org/schema/jbi}provider:ID:127.0.1.1-1284e33a7f0-2:0
]
In: [
content: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:top="http://toplus.examples.andago.com" xmlns:xsd="http://beans.io.examples.andago.com/xsd"><soapenv:Header/><soapenv:Body><top:toPlus><top:tpi><xsd:p1>8</xsd:p1><xsd:p2>9</xsd:p2></top:tpi></top:toPlus></soapenv:Body></soapenv:Envelope>
]
error: [
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
]
]

    • The message content and target is correct but the operation not? I think so.....

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:top="http://toplus.examples.andago.com" xmlns:xsd="http://beans.io.examples.andago.com/xsd"><soapenv:Header/><soapenv:Body><top:toPlus><top:tpi><xsd:p1>8</xsd:p1><xsd:p2>9</xsd:p2></top:tpi></top:toPlus></soapenv:Body></soapenv:Envelope>

target: PropertyMatchingReference{SERVICE_NAME={http://toplus.examples.andago.com}ToPlus-Service}

operation: {http://routing.examples.andago.com}routing

The operation should be {http://toplus.examples.andago.com}toPlus, shouldn't it? Or is it nothing to do with the NullPointerException.

I atached both wsdls (consumer and provider).
ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 10:49 AM   in response to: fsalceda in response to: fsalceda
  Click to reply to this thread Reply
Hi,

Yeah, it's the mismatch operationName cause the problem, that will cause cxf bc provider endpoint get a NULL BindingOperationInfo instance.

You need set correct operationName for the MessageExchange also from camel router.

Freeman
fsalceda

Posts: 79
Registered: 01/29/10
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 12:47 PM   in response to: ffang in response to: ffang
  Click to reply to this thread Reply
Now I route to the endpoint:

<to uri="jbi:service:http://toplus.examples.andago.com/ToPlus-Service?operation=http://toplus.examples.andago.com:toPlus"/>

But I got the same Exception. Is it the correct way to do that?

The JbiOperation property is still the original one:
JbiOperation = {http://routing.examples.andago.com}routing

When you said "also from camel router" did you mean that I have to configure the targetOperation in the provider and also from camel router? If It were so, can't I use a provider binding component to invoke more than one operation of a web service???

Log Message was:

14:45:09,956 | DEBUG | -cxf-bc-thread-4 | NMR | .servicemix.nmr.core.ChannelImpl 198 | Channel org.apache.servicemix.nmr.core.ChannelImpl@1fee2db delivering exchange: [
id: 8454ff20-7e70-4bd0-a462-a827d9b788d1
mep: InOut
status: Error
role: Provider
target: PropertyMatchingReference{SERVICE_NAME={http://toplus.examples.andago.com}ToPlus-Service}
operation: http://toplus.examples.andago.com:toPlus
properties: [
javax.jbi.ServiceEndpoint = org.apache.servicemix.jbi.runtime.impl.ServiceEndpointImpl@78014a
javax.jbi.messaging.MessageExchange = org.apache.servicemix.jbi.runtime.impl.InOutImpl@767bef
javax.jbi.messaging.sendSync = <null>
javax.jbi.servicedesc.ServiceEndpoint = org.apache.servicemix.jbi.runtime.impl.EndpointImpl@a21de3
CamelToEndpoint = service:http://toplus.examples.andago.com/ToPlus-Serviceoperation=http%3A%2F%2Ftoplus.examples.andago.com%3AtoPlus
JbiOperation = {http://routing.examples.andago.com}routing
javax.jbi.ServiceName = {http://toplus.examples.andago.com}ToPlus-Service
org.apache.servicemix.correlationId = fdd1755f-8cb0-4e4e-907e-c66aadf9c7de
javax.jbi.transaction.jta = <null>
javax.jbi.InterfaceName = <null>
org.apache.servicemix.senderEndpoint = {http://camel.apache.org/schema/jbi}provider:ID:127.0.1.1-1284e33a7f0-6:0
]
In: [
content: javax.xml.transform.sax.SAXSource@c29ba3
]
error: [
java.lang.NullPointerException
at org.apache.servicemix.cxfbc.CxfBcProvider.process(CxfBcProvider.java:206)
at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:627)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:581)
at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchangeInTx(AsyncBaseLifeCycle.java:478)
at org.apache.servicemix.common.AsyncBaseLifeCycle$2.run(AsyncBaseLifeCycle.java:347)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)
]
]

Edited by: fsalceda on Apr 30, 2010 12:48 PM

Edited by: fsalceda on Apr 30, 2010 12:49 PM

ffang

Posts: 1,320
Registered: 12/24/07
Re: Camel Router to a Web Service (InOut)
Posted: Apr 30, 2010 2:28 PM   in response to: fsalceda in response to: fsalceda
  Click to reply to this thread Reply
Hi,
You need check the operation in MessageExchange(it's smx used exchange) but not from camel exchange header.

From the log, your configuration take effect, notice this line

operation: http://toplus.examples.andago.com:toPlus

but this is not correct, we should use some syntax like
{namespaceuri}local
so it should be
{http://toplus.examples.andago.com}toPlus

So use
<to uri="jbi:service:http://toplus.examples.andago.com/ToPlus-Service?operation={http://toplus.examples.andago.com}toPlus"/>

but not
<to uri="jbi:service:http://toplus.examples.andago.com/ToPlus-Service?operation=http://toplus.examples.andago.com:toPlus"/>

And you needn't specify operationName for cxfbc provider endpoint, of course it support multiple operations in one portType.

Freeman
fsalceda

Posts: 79
Registered: 01/29/10
Re: Camel Router to a Web Service (InOut)
Posted: May 3, 2010 3:51 PM   in response to: ffang in response to: ffang
  Click to reply to this thread Reply
Thanks a lot to all. Now it works!!!