DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Aggregating REST APIs Calls Using Apache Camel
  • REST Services With Apache Camel
  • Spring Boot Microservices + Apache Camel: A Hello World Example
  • Building an Image Classification Pipeline With Apache Camel and Deep Java Library (DJL)

Trending

  • Stop Writing Dialect-Specific SQL: A Unified Query Builder for Node.js
  • 11 Agentic Testing Tools to Know in 2026
  • Genkit Middleware: Intercept, Extend, and Harden your Gen AI Pipelines
  • Hallucination Has Real Consequences — Lessons From Building AI Systems
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. SOAP Transformation With Apache Camel Java DSL

SOAP Transformation With Apache Camel Java DSL

Got a bunch of SOAP services staring you in the face? Fear not!

By 
Raffael Mendes user avatar
Raffael Mendes
·
Dec. 23, 20 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
14.4K Views

Join the DZone community and get the full member experience.

Join For Free

One of the most common issues that we usually tackle with customers when modernizing legacy integrations is when they have a collection of legacy SOAP web services that don't integrate well enough with the modern RESTful-based clients.

In this article, we are going to use Apache Camel to build a REST endpoint that will translate REST calls to a SOAP envelope, get the response, and send it back to the client.

Apache Camel is a popular open-source integration framework with lots of features and a diverse ecosystem of plugins and libraries. That said, this implementation is a case of Message Transformation. To be more specific, this is a use case of the Normalizer pattern.

The code for this implementation is available on GitHub.

First Things First

If we're going to translate a SOAP service, first we need a SOAP service. For this example, we're going to use Learn Web Services' Temp Converter Service available at this link.

Maven Is Your Friend

Now, we don't actually need to write all the code that is needed to interact with a SOAP web service. We can use the Apache CXF CodeGen Plugin to create the source code from the WSDL. To do that, you just need to add the plugin to the pom.xml

XML
 




x


 
1
<plugin>
2
                <groupId>org.apache.cxf</groupId>
3
                <artifactId>cxf-codegen-plugin</artifactId>
4
                <executions>
5
                    <execution>
6
                        <id>generate-sources</id>
7
                        <phase>generate-sources</phase>
8
                        <configuration>
9
                            <wsdlOptions>
10
                                <wsdlOption>
11
                                    <wsdl>src/main/resources/TempConverter.wsdl</wsdl>
12
                                </wsdlOption>
13
                            </wsdlOptions>
14
                        </configuration>
15
                        <goals>
16
                            <goal>wsdl2java</goal>
17
                        </goals>
18
                    </execution>
19
                </executions>
20
            </plugin>



And then run mvn generate-sources. This will generate all the necessary boilerplate code under the target folder for Camel to interact with the SOAP endpoints.

To make use of autocompletion resources in IDEs, you can, in Eclipse, right-click -> Build Path -> Use as Source Folder.

Talk Is Cheap, Show Me the Code

We're going to use Spring Boot Starter to make life easier for us, so we just need to annotate to create our beans. The first bean that we will create is the Apache CXF Soap Endpoint config. This bean is going to be responsible for making the request and gathering the response.

Java
 




x


 
1
@Value("${endpoint.wsdl}")
2
    private String SOAP_URL;
3
    
4
    
5
    @Bean(name = "cxfConvertTemp")
6
    public CxfEndpoint buildCxfEndpoint() {
7
        CxfEndpoint cxf = new CxfEndpoint();
8
        cxf.setAddress(SOAP_URL);
9
        cxf.setServiceClass(TempConverterEndpoint.class);
10
        return cxf;
11
    }



With this, we're ready to finally go into some Camel code.

Let's build a route that will consume a parameter exposed by a REST service.

Java
 




xxxxxxxxxx
1
22


 
1
from("direct:celsius-to-fahrenheit")
2
        .removeHeaders("CamelHttp*")
3
        .process(new Processor() {
4
            @Override
5
            public void process(Exchange exchange) throws Exception {
6
                CelsiusToFahrenheitRequest c = new CelsiusToFahrenheitRequest();
7
        c.setTemperatureInCelsius(Double.valueOf(exchange.getIn().getHeader("num").toString()));
8
                exchange.getIn().setBody(c);
9
            }
10
        })
11
        .setHeader(CxfConstants.OPERATION_NAME, constant("{{endpoint.operation.celsius.to.fahrenheit}}"))
12
        .setHeader(CxfConstants.OPERATION_NAMESPACE, constant("{{endpoint.namespace}}"))
13
        .to("cxf:bean:cxfConvertTemp")
14
        .process(new Processor() {
15
            @Override
16
            public void process(Exchange exchange) throws Exception {
17
                MessageContentsList response = (MessageContentsList) exchange.getIn().getBody();
18
                CelsiusToFahrenheitResponse r = (CelsiusToFahrenheitResponse) response.get(0);
19
                exchange.getIn().setBody("Temp in Farenheit: "+r.getTemperatureInFahrenheit());
20
            }
21
        })
22
        .to("mock:output");



Let's break down the code above.

We have two processors, one to create the complex object that will be sent as a SOAP envelope, and one to get the response envelope to an object.

On these two lines below, we get the temperature in Celsius to convert to Fahrenheit.

Java
 




xxxxxxxxxx
1


 
1
CelsiusToFahrenheitRequest c = new CelsiusToFahrenheitRequest();
2
c.setTemperatureInCelsius(Double.valueOf(exchange.getIn().getHeader("num").toString()));



Now we set two headers — the namespace and the operation name. For more information about SOAP and its building blocks, I recommend this link from W3Schools.

Java
 




xxxxxxxxxx
1


 
1
.setHeader(CxfConstants.OPERATION_NAME, constant("{{endpoint.operation.celsius.to.fahrenheit}}"))
2
.setHeader(CxfConstants.OPERATION_NAMESPACE, constant("{{endpoint.address}}"))



All these values are configured in the application.properties file.

Plain Text
 




xxxxxxxxxx
1


 
1
endpoint.operation.fahrenheit.to.celsius=FahrenheitToCelsius
2
endpoint.operation.celsius.to.fahrenheit=CelsiusToFahrenheit
3
logging.level.root=INFO
4
endpoint.namespace=http://learnwebservices.com/services/tempconverter
5
endpoint.wsdl=http://www.learnwebservices.com/services/tempconverter?wsdl



Now we send our request and gather the response:

Java
 




x


 
1
to("cxf:bean:cxfConvertTemp")
2
        .process(new Processor() {
3
            @Override
4
            public void process(Exchange exchange) throws Exception {
5
                MessageContentsList response = (MessageContentsList) exchange.getIn().getBody();
6
                CelsiusToFahrenheitResponse r = (CelsiusToFahrenheitResponse) response.get(0);
7
                exchange.getIn().setBody("Temp in Farenheit: "+r.getTemperatureInFahrenheit());
8
            }
9
        })
10
        .to("mock:output");



And it's....

...Not Done

You may be asking yourself "Ok, we have the Camel route, but how are we going to send the Celsius temperature that we want to convert?" Well, now enters the REST endpoint configuration.

Java
 




x


 
1
        restConfiguration()
2
        .component("undertow").host("0.0.0.0").port(9090).bindingMode(RestBindingMode.auto).scheme("http")
3
            .dataFormatProperty("prettyPrint", "true")
4
            .contextPath("/")
5
                .apiContextPath("/api-doc")
6
                    .apiProperty("api.title", "Camel2Soap")
7
                    .apiProperty("api.version", "1.0")
8
                    .apiProperty("host","")
9
        .enableCORS(true);
10
 
          
11
        rest("/convert")
12
            .get("/celsius/to/fahrenheit/{num}")
13
                .consumes("text/plain").produces("text/plain")
14
                .description("Convert a temperature in Celsius to Fahrenheit")
15
                .param().name("num").type(RestParamType.path).description("Temperature in Celsius").dataType("int").endParam()
16
            .to("direct:celsius-to-fahrenheit")
17
            .get("/fahrenheit/to/celsius/{num}")
18
                .consumes("text/plain").produces("text/plain")
19
                .description("Convert a temperature in Fahrenheit to Celsius")
20
                .param().name("num").type(RestParamType.path).description("Temperature in Fahrenheit").dataType("int").endParam()
21
            .to("direct:fahrenheit-to-celsius");



We add some Swagger documentation to our API as a best practice. And if you don't want to test using the command line, you can use the Swagger Inspector.

Shell
 




xxxxxxxxxx
1


 
1
[rmendes@rmendes ~]$ curl localhost:9090/convert/celsius/to/fahrenheit/50
2
Temp in Farenheit: 122.0



And we're finally done. With this article, I hope that some light can be shed on how to reuse some old SOAP-based web services without rewriting them. And with this Apache Camel approach, we can always apply more patterns to maybe enrich or send the information to multiple destinations, for example.

SOAP Web Protocols Apache Camel Java (programming language) Domain-Specific Language

Opinions expressed by DZone contributors are their own.

Related

  • Aggregating REST APIs Calls Using Apache Camel
  • REST Services With Apache Camel
  • Spring Boot Microservices + Apache Camel: A Hello World Example
  • Building an Image Classification Pipeline With Apache Camel and Deep Java Library (DJL)

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook