I've made good progress on getting this to work, mostly by adding annotations
to my service interface. Everything is working as far as calling the service
from my test. I did have to change from ClientProxyFactoryBean to
JaxWsProxyFactoryBean and set the binding to match the
@BindingType(SOAPBinding.SOAP12HTTP_BINDING) in my service.
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");
Now I'm having issues getting the response wrapped in a soap envelop.
Here's what I'm doing to try and marshal the response.
SoapJaxbDataFormat soap = new
SoapJaxbDataFormat("com.company.app.model",
new ServiceInterfaceStrategy(FooService.class, false));
....
.process(new Processor() {
public void process(Exchange exchange)
throws Exception {
// get the value from the input
List<HashMap> data =
(ArrayList<HashMap>) exchange.getIn().getBody();
// todo: handle value is empty
FooResponse response = new
FooResponse();
response.setGpi(String.valueOf(data.get(0).get("value")));
exchange.getOut().setBody(response);
}
})
.marshal(soap);
The error I'm getting is:
java.lang.ClassCastException: [B cannot be cast to [Ljava.lang.Object;
at
org.apache.camel.component.cxf.DefaultCxfBinding.populateCxfResponseFromExchange(DefaultCxfBinding.java:353)
at
org.apache.camel.component.cxf.CxfConsumer$1.setResponseBack(CxfConsumer.java:210)
at
org.apache.camel.component.cxf.CxfConsumer$1.asyncInvoke(CxfConsumer.java:109)
at
org.apache.camel.component.cxf.CxfConsumer$1.invoke(CxfConsumer.java:74)
Do I have to register a type converter or something to help put the response
body in a SOAP envelop?
Thanks,
Matt
On May 23, 2014, at 9:04 AM, Matt Raible <[email protected]> wrote:
> Hey all,
>
> I have a route that produces a CXF Endpoint.
>
> public class FooRoute extends RouteBuilder {
>
> private String uri = "cxf:/foo?serviceClass=" +
> FooService.class.getName();
>
> @Override
> public void configure() throws Exception {
> from(uri)
> .to("log:input")
> // send the request to the
> route to handle the operation
> // the name of the operation is
> in that header
>
> .recipientList(simple("direct:${header.operationName}"));
> from("direct:findById")
> .process(new Processor() {
> public void process(Exchange exchange)
> throws Exception {
> // get the id from the input
> String id =
> exchange.getIn().getBody(FooRequest.class).getId();
> exchange.getOut().setBody(id);
> }
> })
> .to("sql:select value from table where id =
> #?dataSource=ds")
> .to("log:output")
> .process(new Processor() {
> public void process(Exchange exchange)
> throws Exception {
> // get the value from the input
> List<HashMap> data =
> (ArrayList<HashMap>) exchange.getIn().getBody();
> // todo: handle value is empty
> FooResponse response = new
> FooResponse();
>
> response.setGpi(String.valueOf(data.get(0).get("value")));
>
> exchange.getOut().setBody(response);
> }
> }).end();
> }
> }
>
> This is easy to talk to thanks to CXF's ClientFactoryBean, allowing me to
> call methods directly on the interface.
>
> protected static FooService createCXFClient() {
> // we use CXF to create a client for us as its easier than
> JAXWS and works
> ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
> factory.setServiceClass(FooService.class);
> factory.setAddress(URL);
> return (FooService) factory.create();
> }
>
> One of the things I'd like to do is make this new service
> backwards-compatible with the old one. In other words, I should be able to
> change the endpoint URL in the existing client and everything works the same.
> The existing client uses the javax.xml.soap API to talk to the service. Below
> is a test I wrote that shows how it works. Is it possible to modify my
> route/endpoint so this WS call will work?
>
> SOAPConnection connection =
> SOAPConnectionFactory.newInstance().createConnection();
> SOAPMessage message = MessageFactory.newInstance("SOAP 1.2
> Protocol").createMessage();
> SOAPPart soapPart = message.getSOAPPart();
> SOAPEnvelope envelope = soapPart.getEnvelope();
> envelope.addNamespaceDeclaration("soap",
> "http://www.w3.org/2003/05/soap-envelope");
> envelope.addNamespaceDeclaration("ax22", "http://common.app.company.com/xsd");
> SOAPBody body = envelope.getBody();
> body.addNamespaceDeclaration("m", "http://ws.app.company.com");
>
> ByteArrayOutputStream request = new ByteArrayOutputStream();
> message.writeTo(request);
>
> SOAPElement bodyChildOne = body.addChildElement("CompanyFooRequest", "m");
> SOAPElement bodyChildTwo = bodyChildOne.addChildElement("args0", "m");
> bodyChildTwo.addChildElement("ID", "ax22").addTextNode("123456");
> SOAPMessage reply = connection.call(message,
> "http://localhost:7800/axis2/services/CompanyFooService_2_0");
> if (reply != null) {
> Iterator itr = reply.getSOAPBody().getChildElements();
> Map resultMap = TestUtils.getResults(itr); // TestUtils loops through
> SOAPElements to create a map
> assertEquals("6610012", resultMap.get("value"));
> }
>
> Thanks,
>
> Matt
>