SOAP with Helidon

Lukas Jungmann
Helidon
Published in
4 min readAug 20, 2021

Developing SOAP-based web services and deploying them as microservices can be a challenging task. In this article, we’ll demonstrate how you can develop a simple SOAP-based web service using Eclipse Metro and then run it on Helidon WebServer without having to move a full-featured Java EE application server to a docker image.

Set up a project

For this tutorial, we’ll use the Helidon SE quick-start archetype:

mvn -U archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-se \
-DarchetypeVersion=2.3.0 \
-DgroupId=org.glassfish.metro \
-DartifactId=helidon-sample \
-Dpackage=org.glassfish.metro.helidon.sample

Add Dependencies

Next, add a dependency on Eclipse Metro to the project. Since Eclipse Metro primarily targets Java EE/Jakarta EE runtime environments, which Helidon does not provide, we need a connector to integrate Eclipse Metro with Helidon. To use the connector, add org.glassfish.netro:helidon-se as a first dependency in the pom file of the project we’ve created in previous step::

<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>helidon-se</artifactId>
<version>1.0.1</version>
</dependency>

This also brings in all other required dependencies we need, so we do not need to define them explicitly.

Create a SOAP-based Web Service

Using the “Hello World” example, create a typical SOAP-based web service that greets the caller:

package org.glassfish.metro.helidon.sample;import javax.jws.WebService;@WebService
public class GreetSOAP {
public String hello(String who) {
return "Hello " + who;
}
}

This is no difference from other SOAP-based web services we’ve seen. You can use the same set of annotations from “old” Java EE days. Those familiar with developing web services for Tomcat will be familiar with the next file we have to create — sun-jaxws.xml resource file — with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name="SoapWs"
implementation="org.glassfish.metro.helidon.sample.GreetSOAP"
url-pattern="/SoapWsService">
</endpoint>
</endpoints>

More details about this descriptor file can be found in Metro documentation.

Now we can make the web service responding to requests on Helidon WebServer by updating createRouting method we have in Main class:

private static Routing createRouting(Config config) {
MetroSupport ms = MetroSupport.builder()
.dumpService(true) //print SOAP messages to the log
.build();
...
return Routing.builder()
...
.register(ms)
.build();
}

Build and run the project

> mvn package
> java -jar target/helidon-sample.jar

To verify the service is up and running, we can check the WSDL file at http://localhost:8080/SoapWsService?WSDL.

Consuming the SOAP service

The best way to test the service is to consume it, so let’s create another project where that can be done:

mvn -U archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-se \
-DarchetypeVersion=2.3.0 \
-DgroupId=org.glassfish.metro \
-DartifactId=helidon-sample.client \
-Dpackage=org.glassfish.metro.helidon.sample.client

The very first thing we have to do is change the default port that Helidon SE WebServer listens on in the application.yaml — let’s change it to 8081.

Next, we need to add a dependency on the Metro — Helidon integration layer, just as we did when we created the project with the service:

<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>helidon-se</artifactId>
<version>1.0.1</version>
</dependency>

Call wsimport which can generate portable java artifacts from the WSDL file:

<plugin>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3.5</version>
<executions>
<execution>
<id>create-client</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<packageName>org.glassfish.metro.helidon.sample.client</packageName>
<wsdlUrls>
<wsdlUrl>http://localhost:8080/SoapWsService?WSDL</wsdlUrl>
</wsdlUrls>
</configuration>
</execution>
</executions>
</plugin>

Create a Helidon service where we call the service:

package org.glassfish.metro.helidon.sample.client;

import io.helidon.faulttolerance.Async;
import io.helidon.webserver.Routing;
import io.helidon.webserver.ServerRequest;
import io.helidon.webserver.ServerResponse;
import io.helidon.webserver.Service;

public class GreetClient implements Service {

private GreetSOAP port;

@Override
public void update(Routing.Rules rules) {
rules.get("/client", this::soapCall);
}

private void soapCall(ServerRequest request, ServerResponse response) {
//the call to web service is blocking,
//therefore to avoid blocking the web server
//we have to wrap the call into Async
Async a = Async.create();
a.invoke(() ->
call(request.queryParams().first("who").orElse("You")))
.thenApply(response::send);
}

private GreetSOAP getPort() {
if (port == null) {
port = new GreetSOAPService().getGreetSOAPPort();
}
return port;
}

private String call(String s) {
return getPort().hello(s) + "!\n";
}
}

Register the service in the createRouting method we have in Main class:

private static Routing createRouting(Config config) {
...
return Routing.builder()
...
.register("/metro", new GreetClient())
.build();
}

And build and run our app:

> mvn package
> java -jar target/helidon-sample.client.jar

Now its time for the real test:

> curl http://localhost:8081/metro/client?who=Joe
Hello Joe!

Frequently Asked Questions

Nice example, but I’m interested in Helidon MP. How can I make this work with MP?

There only difference is that we need to use org.glassfish.metro:helidon-mp instead of org.glassfish.metro:helidon-se in our pom. We also do not have to update the createReouting method.

I want to use Jakarta EE version of the APIs/jakarta packages, not Java EE/javax. Is that possible?

There are two versions of the helidon-se/helidon-mp artifacts — 1.x.y supporting “old” Metro 2.xfrom Java EE with javax package namespace and 2.x.y supporting “new” Metro 3.x from Jakarta EE with jakarta package namespace.

Where can I find more examples?

The Source code, together with more advanced samples, is available on GitHub. Java EE version of the same can be found in the EE8 branch in the same repository.

Where can I find Metro documentation?

Basic usage is covered by jax-ws userguide, advanced features are covered in Metro userguide. Documentation for maven-plugin is available here. Documentation for MetroSupport and available configuration options is on GitHub.

Where can I file a bug/RFE?

At https://github.com/eclipse-ee4j/metro-jax-ws/issues

Conclusion

In this article we’ve shown how to develop simple SOAP-based web service with Eclipse Metro, run it on Helidon WebServer, and then call the service. In the FAQ section, we’ve also provided guidance on extending this sample to be used in the context of Helidon MP and what needs to be changed in order to be able to use new Jakarta EE APIs.

--

--