Did you know: programmers convert coffe to code?

If you like my articles, support me with a small amount.


Buy me a coffee

Web Service client with Spring

I have encountered a task where we had to create a website client to send data to our web-service to enable bulk data import for testing purposes. In this article I will show you how you can create your own client with Spring — without any Spring Boot requirements.

The task

The idea of the task comes from the Spring.io website Consuming a SOAP web service. As you will see, it uses Spring Boot Starter to achieve the consuming of the SOAP web service. Well, I have found this too much work and too many dependencies so I’ve taken a look how I could run the script without Spring Boot — because I do not need the boot features it offers.

The solution

As I’ve already mentioned, the solution is based on the Spring.io example but I cut down the unnecessary things like Spring Boot.

Parent project

Well, if we start with the example’s pom.xml file, we see that it is based on a parent-pom: spring-boot-starter-parent.

For my solution we do not need any parent-pom, it is perfectly fine to create a simple empty project without any pre-defined dependencies or parents.

My basic configuration looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>hu.japy.dev</groupId>
    <artifactId>webservice-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Web-Service Client with Spring</name>
    <description>A simple example project where we create a webservice client with Spring</description>
</project>

Dependencies

The project requires only one dependency to include: org.springframework.ws:spring-ws-core. For easier changing in the future I have defined a property which holds the version number of this property. The whole dependency-declaration with the property look like this:

<properties>
    <spring.ws.version>2.3.0.RELEASE</spring.ws.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-core</artifactId>
        <version>${spring.ws.version}</version>
    </dependency>
</dependencies>

Class generation

Because we are using a WSDL file we need to generate the classes during compile time. An alternative would be to create the interface objects (DTOs) manually, but this would require manual updates every time there are changes in the remote contract. Another way would be to create the DTOs once automatically and use them later — but again in this case it would require another generation run if we find there is something wrong. Generating the classes at compile-time is something good because if the DTOs change you will likely get a compile error when you re-build your application. For class-generation you can take the example from the Spring.io tutorial:

<build>
    <plugins>
        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <version>0.12.3</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaLanguage>WSDL</schemaLanguage>
                <generatePackage>hu.japy.dev.ws</generatePackage>
                <generateDirectory>target/generated-sources/java</generateDirectory>
                <schemas>
                    <schema>
                        <fileset>
                            <directory>src/main/resources/wsdl</directory>
                            <include>Weather.wsdl</include>
                        </fileset>
                    </schema>
                </schemas>
            </configuration>
        </plugin>
    </plugins>
</build>

Alternatively you could have the WSDL locally — if it is your project or you have access to the most actual WSDL file. In this case you have to change the line with the <url> to the following:

&lt;fileset&gt;
    &lt;directory&gt;src/main/resources/wsdl&lt;/directory&gt;
    &lt;include&gt;Weather.wsdl&lt;/include&gt;
&lt;/fileset&gt;

This would load the Weather.wsdl file from the src/main/resources/wsdl folder.

Packaging

Because Spring Boot can package your whole project into a single executable file I will add this feature too. For this I use the Maven Shade plug-in which creates a so called “ueberjar” from the project’s contents. To add this plugin to the project simply include the following plug-in into the <build><plugins> section created in the previous section where we added the automatic code generation from the WSDL:

&lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.4.3&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;phase&gt;package&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;shade&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;transformers&gt;
                    &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;
                        &lt;mainClass&gt;hu.japy.dev.webclient.Main&lt;/mainClass&gt;
                    &lt;/transformer&gt;
                &lt;/transformers&gt;
                &lt;artifactSet&gt;
                    &lt;excludes&gt;
                        &lt;exclude&gt;testng:testng&lt;/exclude&gt;
                        &lt;exclude&gt;org.mockito:*&lt;/exclude&gt;
                        &lt;exclude&gt;org.apache.maven:lib:tests&lt;/exclude&gt;
                    &lt;/excludes&gt;
                &lt;/artifactSet&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;

For a detailed description on how Maven Shade works refer to a previous article of mine.

Code changes

The code changes in contrast to the example of Spring.io are only in the Main class. There is no need to add the @SpringBootApplication annotation because we are not running a Spring Boot app. However the context has to be created for the application and from the context we have to get the bean. The Main class looks like this:

package hu.japy.dev.webclient;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import hu.japy.dev.webclient.ws.WebServiceClient;
import hu.japy.dev.webclient.ws.WebServiceClientConfiguration;

/**
* @author GHajba
*
*/
public class Main {

    public static void main(final String... args) {

        ConfigurableApplicationContext ctx = null;
        try {
            ctx = new AnnotationConfigApplicationContext(
            WebServiceClientConfiguration.class);
            WebServiceClient client = ctx.getBean(WebServiceClient.class);
            client.doWork();
        } finally {
            if (ctx != null) {
                ctx.close();
            }
        }
    }
}

The problem with this approach is that it uses a hard-coded ZIP currently. And this was all the code change needed in the application.

Proxy

Another interesting part is trying this example application at the company where you are behind a corporate proxy. Fortunately this is not a big problem, you can easily add support for proxy connections. To have proxy enabled, open the Main class and add the following to the main method right at the beginning:

System.getProperties().put(&quot;proxySet&quot;, &quot;true&quot;);
System.setProperty(&quot;proxyHost&quot;, &quot;your.proxy.host&quot;);
System.setProperty(&quot;proxyPort&quot;, &quot;proxyPortNumber&quot;);

Naturally you could add the proxy connection instead of hard-coding it to your application with some comman-line-parser, but this topic doesn’t fit into this article. If you are interested, just let me know, and I’ll write another article where I cover argument parsing.

Conclusion

As you could see, you can use the basic example application from the Spring.io website even without Spring Boot added. You only have to know how you can add the same functionality without the “magic” what’s done by the Spring Boot project. This enables you to integrate different parts of the Spring ecosystem to your projects based on the tutorials provided at the Spring.io website.

GHajba
 

Senior developer, consultant, author, mentor, apprentice. I love to share my knowledge and insights what I achieve through my daily work which is not trivial -- at least not for me.

Click Here to Leave a Comment Below 0 comments