Rest-SOAP gateaway for external services (Spring + Camel)

10,546

Solution 1

There is no straight forward way to simply proxy between soap and rest. REST services, is all about resources and CRUD - create/read/update/delete. The payload can be whatever, often JSON, but XML, plain text or any orther format is valid. SOAP is XML only with custom definied methods.

I understand the confusion about all the components related to this in Camel.

There are a few aspects you need to have in mind, while chosing your approach.

  • How much of the SOAP stack do you really need? Most likely you only want the basic featuers, such as receiving a simple soap-envelope and extract the payload without WS-addressing, ws-security etc. etc.

  • Do you have a contract first or code first approach? That is, do you have your soap service already definied by java classes/interfaces or do you have a WSDL?

  • Do you have your camel instance deployed inside a servlet container (which is quite common), such as Tomcat, Jetty or a JavaEE app server? If you, you might need to use that servlet container to handle requests by some reason (to get all requests from the same port/server/Domain name by some reason such as web server virtual host, firewalls etc). Then CXF might ge a bit tricky. Otherwise, camel can put up listeners with the built-in jetty core.

So: Contract first and camel inside serverletcontainer - I prefer spring-ws, since it's very easy to get started with. spring-ws component. Just do the initial wireing in spring and you do not even need to generate things from a WSDL, just simply point out which soap-action, uri or rootq name to get messages from:

from("spring-ws:soapaction:http://example.com/GetFoo?endpointMapping=#endpointMapping")

then you have the XML.

If you need to host the web service from camel, CXF in payload mode is quite decent and will behave pretty much the same.

from("cxf:somename:http://localhost:8765?wsdl=somewsdlfile.wsdl&dataFormat=PAYLOAD")

If you have the service definied in Java already, you could use the SOAP dataformat with the Jetty component to get a very lightweight solution.

SoapJaxbDataFormat soap = new SoapJaxbDataFormat("com.example.customerservice", new      ServiceInterfaceStrategy(CustomerService.class));
from("jetty:http://localhost:9832/soapsrv")
  .marshal(soap) // and other transforms here
  .to("http://somerestservicehost/srv");

Or. go with the full CXF solution with CXF or CXF-bean. There are plenty of examples on the camel website. But the component is rather large and can be somewhat tricky.

For rest, there are also choices, but that part is more straight forward. Rest is very much about creating some content (by extracting it from the soap message, and perhaps map xml to json), which might be easiest to achieve with some plain old java code. Then just invoke a HTTP endpoint towards your rest server. The HTTP4 or HTTP component will do a lot of this for you.

CXFRS is good if you like CXF, and can provide some help, specifically if you want to model your rest service with classes

Solution 2

Camel CXF will do the trick for your soap endpoint.

First you need to write an endpoint

@WebService
public interface QuoteInEndpoint {

  @WebResult(name = "quote")
  public Quote price(@WebParam(name = "symbol") String symbol);

}

Then you need to declare it

<cxf:cxfEndpoint id="quoteIn" address="http://localhost:9002" serviceClass="my.package.QuoteInEndpoint" />

You can then build a route from this endpoint

from("cxf:bean:quoteIn")//
        .process(new Processor() {
          @Override
          public void process(Exchange exchange) throws Exception {
            //do whatever you need to get your object and transform it for your rest service
          }
        })//
        .to("http://myplayframeworkserver/myservice")//

Camel will start the route, expose the wsdl of your soap service at localhost:9002, and every soap request will be send to your rest server. The process method can be use to shape your objects to the correct format for your rest service (I assume json). Instead of using a processor, you might use another Camel component to do the job (Camel JSON if you need json)

Share:
10,546
JohnGray
Author by

JohnGray

Updated on July 28, 2022

Comments

  • JohnGray
    JohnGray over 1 year

    I need to build REST-SOAP gateaway between 2 external services First web services makes SOAP requests and awaits SOAP response. Second service (mine, written in Play Framework 1.2.4) works only using RESTful approach. I don`t want to integrate SOAP related things with second service for many reasons. So I need some third service to act between them.

    I have looked into using Spring web-app with Apache Camel, but still can't get the full picture because there are so many modules for Camel. CXF-RS and SOAP components looks promissing, but I can't figure out how to implement proxying using them.

    First of all, how to make Camel listen for the specified SOAP request. And then, how to route response from RESTful service back to calling service.

    I tried to do it using only spring configuration.

  • JohnGray
    JohnGray almost 12 years
    Thanks for your answer and for the code samples! But soap service is not mine. It is provided by another company. I just to proxy request-response between my REST service and their SOAP service.
  • JohnGray
    JohnGray almost 12 years
    Thanks! The SpringWS looks promissing. If it can listen for requests from external (very external :)) SOAP service.
  • Alon
    Alon over 5 years
    You showed how to convert one URL to another, but when converting a REST request to SOAP, I will also need to convert the HTTP method. e.g. for updating an object I will often have to convert PUT to POST. Is it possible to do that using Camel?
  • Petter Nordlander
    Petter Nordlander over 5 years
    If you need to explicitly configure the method, do something like this: .setHeader(Exchange.HTTP_METHOD, constant("POST"))