I'm using Camel and have generated code from a WSDL using CXF. I generated a client stub and the implementation appears like this:
SetDeviceDetailsv4 port = ss.getSetDeviceDetailsv4Port();
com.vodafone.gdsp.ws.SetDeviceDetailsv4_Type _setDeviceDetailsv4_parameters = null;
com.vodafone.gdsp.ws.GdspHeader _setDeviceDetailsv4_gdspHeader = null;
com.vodafone.gdsp.ws.SetDeviceDetailsv4Response _setDeviceDetailsv4__return = port.setDeviceDetailsv4(_setDeviceDetailsv4_parameters, _setDeviceDetailsv4_gdspHeader);
System.out.println("setDeviceDetailsv4.result=" + _setDeviceDetailsv4__return);
As you one can see, the port takes two parameters and returns the response, which I want to delegate back to my Camel Route. What's the best way to implement this in Camel? I already have my CXF Enpoint defined, I'm just struggling with the DSL Routing part of it. Should I add a processor like what is found in this link? Apache Camel and web services
Thanks
You can use jax-ws client (implement as bean) and use it in camel DSL. JAX-WS client bean definition takes service class/interface and allow you configure additional properties like SSL config & etc. In route, we can use it as bean. It takes JAXB generated Request object (WSDL request object) as input and returns the JAXB generated Response Object (WSDL response object). To convert you pojo to JAXB classes, Dozer framework can be used or custom mapping can be also used.
Jax-WS client is also flexible to take XML as request and response. In that case, properties need to be set as DATAFORMAT as PAYLOAD.
I'm not sure if this is the correct way to do it but I added both of my "input" objects as a Camel Header, then I wrote a processor that grabbed what I needed and put the two objects that the service call needed as parameters.
public void process(Exchange exchange) throws Exception {
Message inMessage = exchange.getIn();
gdspHeader = inMessage.getHeader(GDSP_HEADER, com.vodafone.gdsp.ws.GdspHeader.class);
commModule = inMessage.getHeader(COMM_MODULE_HEADER, resmed.hi.ngcs.datastore.model.CommModule.class);
SetDeviceDetailsv4_Type deviceDetails = createSetDeviceDetailsv4(commModule);
List<Object> params = new ArrayList<>();
params.add(deviceDetails);
params.add(gdspHeader);
inMessage.setBody(params);
}
`
Related
I have to integrate our j2ee application with a REST webservice. And I wanted to use the RestEasy JAX-RS implementation from JBoss. The webservice returns an array in JSON format. I've this piece of code:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://myservices.com/schemes/all");
Response response = target.request().get();
Can I map this "response" object to List<Scheme> using RestEasy? Thanks
Provided that your JSON provider is capable of converting JSON to appropriate entities, then yes. The get method you call in the code has an overloaded version which accepts the class of entity to which the result is to be converted. Since there are problems with serializing certain collections' implementations, your type has to be wrapped in GenericType class, like that:
List<Scheme> schema = [...].get(new GenericType<List<Scheme>>(){});
The above method should work with just about every JAX-RS-compliant implementation.
You can also use Jackson library, which allows you (amongst other things) to pass collections without need of wrapping them.
Having a SOAP based web service with XML payload, how can I grab the XML payload of the service response in JAX-WS >2.0 client?
I can see how this question will be marked as duplicate, but bear with me.
It seems that the options are:
Use Dispatch API. However this would require me to go low(er) level and create the request payload manually, which I want to avoid.
Use handler infrastructure of the JAX-WS to grab the payload and possibly pass it via MessageContext property back to the client, but this will still unmarshall the XML into JAXB Object tree, which I want to avoid.
So, how can I:
Call a web service using SEI - no messing with creating XML request from scratch
Grab the 'RAW' XML response without the JAXB unmarshalling happening
Sounds simple enough, right?
Among the non-goals the JAX-WS 2 specification says that
'Pluggable data binding JAX-WS 2.0 will defer data binding to JAXB[10]; it is not a goal to provide a
plug-in API to allow other types of data binding technologies to be used in place of JAXB. However,
JAX-WS 2.0 will maintain the capability to selectively disable data binding to provide an XML based
fragment suitable for use as input to alternative data binding technologies.'
So, you should be able to have access to the raw payload.
The following example is also in the specification :
4.3.5.5 Asynchronous, Callback, Payload-Oriented
class MyHandler implements AsyncHandler<Source> {
...
public void handleResponse(Response<Source> res) {
Source resMsg = res.get();
// do something with the results
}
}
Source reqMsg = ...;
Service service = ...;
Dispatch<Source> disp = service.createDispatch(portName,
Source.class, PAYLOAD);
MyHandler handler = new MyHandler();
disp.invokeAsync(reqMsg, handler);
Since the specification also states that a Binding has its own HandlerChain (see chapter 9) you should be able to remove the JAXB handler from the chain, so that JAXB marshalling/unmarshalling doesn't get involved.
I'm currently trying to get familiar with Servicemix, Camel, CXF, etc. and have basically the same question as somebody had four years ago here:
How do I convert my BeanInvocation object in camel to a message body and headers?
Unfortunately, the answer there don't help me much. As one of the answers mentions: all examples on the Camel website concern themselves with sending something to a bean from CXF.
I have a bean proxy endpoint that I'm using in a POJO, injected via
#Produce(uri ="direct:start")
MyService producer; //public interface example.MyService { void myMethod(MyObject o);}
When I use another bean endpoint at the other end, implementing a consumer for that interface, this all works fine. What I now would like to do is to use camel-cxf to consume a web service implementing that interface instead. I created a cxfEndpoint via:
<cxf:cxfEndpoint id="cxfEndpoint"
address="http://localhost:8080/MyService/services/MyService"
wsdlURL="http://localhost:8080/MyService/services/MyService?wsdl"
serviceName="s:MyService"
serviceClass="example.MyService"
endpointName="s:MyService"
xmlns:s="http://example" />
What I'm now basically trying to do is, in a RouteBuilder:
from( "direct:start" ).to( "cxf:bean:cxfEndpoint" );
but get an Exception, when trying invoke something on the proxy object:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Part
{http://example}o should be of type example.MyObject, not
org.apache.camel.component.bean.BeanInvocation
From what I understand, the Spring proxy object generates a BeanInvocation object that can be consumed by another bean endpoint, and I have to transform this into a way the cxf can generate a SOAP request out of it (or is there some automatic conversion?).
But I'm kind of stuck doing that:
I tried soap marshalling as described at http://camel.apache.org/soap.html or writing my own Processor, but I'm not even sure if I just failed, or if that's not how it's supposed to work. I also tried to set the cxfEndpoint into the different message modes without success.
Any pointers what I should be generally doing would be greatly appreciated!
So after a week of trial and error, I found that the answer is quite simple. If the cxfEndpoint is set to POJO mode (the default), the solution is to just grab the invocation parameters and stuff them into the message body instead:
from( "direct:start" ).process( new Processor() {
#Override
public void process( Exchange e) throws Exception {
final BeanInvocation bi = e.getIn().getBody( BeanInvocation.class );
e.getIn().setBody( bi.getArgs() );
}
} ).to( "cxf:bean:cxfEndpoint" )
I guess this could be done more elegantly somehow though.
Im using camel proxy to call an endpoint in camel say direct:say.
public interface xyz{
public void sayhello(String body,??????);
}
??? i want to set headers or send headers can any one help with an example in binding interface.
Thanks
Saitsh
You should have a look at http://camel.apache.org/parameter-binding-annotations.html. One nifty example:
public void sayhello(#Header("user") String user, #Body String body, Exchange exchange) {
exchange.getIn().setBody(body + "MyBean");
}
Beside that following annotations are available:
#Headers to bind to the Map of the inbound message headers
#OutHeaders to bind to the Map of the outbound message headers
Very quick leads...
look at http://camel.apache.org/bean and http://camel.apache.org/bean-binding.html
JndiContext context = new JndiContext();
context.bind("xyz", new XyzImp());
CamelContext camelContext = new DefaultCamelContext(context);
then you can call
to("bean:xyz?method=sayhello(${body}, ${headers})")
or you can add annotation to you interface
sayhello(#Body String body,#Headers Map headers);
and then
to("bean:xyz?method=sayhello(*, *)")
or
to("bean:xyz?method=sayhello")
should be enough...
The BIG question is, how do you instantiate your xyz interface? Is it singleton or you need a fresh instance for each message or one per thread? But that would be different question :)
Camel 2.16+
Use native proxy parameter binding as described here: http://camel.apache.org/using-camelproxy.html ("What is send on the Message" section).
Previous versions
There no standard way of parameter binding for Camel route proxy. Only one String argument can be bound to exchange body.
But you can create custom implementation of InvocationHandler which will extend Camel core AbstractCamelInvocationHandler class and provide desired parameter binding by overriding of invokeWithbody(...) method.
Check Camel ProxyUtil.createProxyObject(...) method to understand how proxy object is initiated.
I have a REST server which sends JSON in response body. I have recently started reading about Apache Camel. I use following to send requests to my REST service.
from("direct:start").setHeader("token", simple("234da"))
.to("http://localhost:8088/foo/bar/?foo1=bar1");
Now the response will be a JSON, is there any way I get this JSON directly into a POJO using some method ahead of to() (something like this)?
to("http://localhost:8088/foo/bar/?foo1=bar1").toPOJO();
I would prefer a non Spring solution.
Thanks
Little details from my side - although late
Create jsonFormatter and then unmarshal with class you need
JsonDataFormat jsonDataFormat = new JsonDataFormat(JsonLibrary.Jackson);
this can be used in marshalling
from("direct:consume-rest")
.log("calling bean method...")
.to("http://localhost:8080/greeting?name=baba")
//.process(svProcessor) // any extra process if you want
.unmarshal().json(JsonLibrary.Jackson, Greeting.class)
.bean(GreetingHelper.class, "print")
.log("converted to bean ...")
.end()
;
Helper class method
public void print (#Body Greeting greeting) {
Apache Camel provides a component to marshal and unmarshal POJO to and from JSON.
In your case, it would be :
from("direct:start").setHeader("token", simple("234da"))
.to("http://localhost:8088/foo/bar/?foo1=bar1")
.unmarshal().json();
By the way, you may need to configure your json library to do it and I suggest you take look at the official configuration.