Java SOAP Server with Apache CXF and Spring

imageRecently, several articles have appeared that talk about the SOAP protocol , as well as describe the process of creating a server in various languages ​​and platforms. Let's continue the topic. This article will describe how to create a Java server using Apache CXF and Spring Framework. It is assumed that the reader already has a general understanding of the protocol mentioned, as well as working with ant and maven. To make the task a little more interesting, we add the initial condition: given a WSDL scheme describing a web service. So ...
(Picture from an article on Wikipedia .)

0. Initial conditions


The task we have set: it is necessary to implement a web service that meets the SOAP 1.1 specification , based on a ready-made WSDL-scheme. As a protocol for transmitting "envelopes" we will use HTTP. Thus, our task can be divided into two components:
  • creating a java interface based on a WSDL scheme;
  • implementation of a web service based on the resulting interface.

On the first point it is worth making the following remark. In the particular case, we could manually describe the operations we need, but in the general case it is more convenient to use a tool for automatically generating the interface.

This is what the original WSDL scheme looks like:

The service has a very simple functionality: it returns the current time in the specified time zone. In the case when the belt is not specified, the service returns the current server time.

In the process, we will use the following tools:

All of them together are very convenient to use with IntelliJ IDEA , but this tool is optional.

Project structure


Define the structure of the project. In the build folder we will store scripts for ant. In the ObjectLibrary module we will keep the source circuit, as well as the classes generated by it. The CurrentTimeService module will be the main one, we will keep the service implementation in it, and we will also collect the war file from it.

In pom-files we indicate the dependencies necessary for the modules. We will not have many external dependencies: spring-web, log4j, cxf-rt-frontend-jaxws and cxf-rt-transports-http - they are all available at http://repo1.maven.org/maven2 .

1. Creation of a java-interface based on a WSDL-scheme


To automatically generate a java-interface based on a WSDL-scheme, we will use the wsdl2java utility from the Apache CXF package. We slightly modify the original ant-script so that it first cleans up the directory into which java classes will be added. This can be useful if in the future the original circuit will change. By default, the directory is not cleared, which can lead to the appearance of "garbage" from classes that are no longer used. This problem is typical for circuits incorporating complex composite types.


Place this script in the build / build.xml file. Run the task regenerate.object.library , as a result of which in the ObjectLibrary folder we get the interface we need.

package me.artspb.cts;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;
/**
 * This class was generated by Apache CXF 2.5.2
 * 2012-02-02T17:39:35.466+04:00
 * Generated source version: 2.5.2
 * 
 */
@WebService(targetNamespace = "http://artspb.me/cts", name = "CurrentTimeService")
@XmlSeeAlso({ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface CurrentTimeService {
    @WebResult(name = "currentTime", targetNamespace = "http://artspb.me/cts", partName = "currentTime")
    @WebMethod(action = "http://artspb.me/cts")
    public javax.xml.datatype.XMLGregorianCalendar getCurrentTime(
        @WebParam(partName = "timeZoneId", name = "timeZoneId", targetNamespace = "http://artspb.me/cts")
        java.lang.String timeZoneId
    );
}


It should be borne in mind that with the help of the wsdl2java utility we could immediately get a ready-made server (-server switch) and even an implementation for it (-impl switch). However, in the framework of this article, we will use it only to obtain the interface we need in order to avoid tight binding to the generated code.

2. Web service implementation based on the received interface


The implementation of the CurrentTimeService interface will be placed in the module of the same name. The code is straightforward and does not need additional comments.

package me.artspb.cts;
import org.apache.log4j.Logger;
import javax.jws.WebParam;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class CurrentTimeServiceImpl implements CurrentTimeService {
    private Logger logger = Logger.getLogger(CurrentTimeServiceImpl.class);
    public XMLGregorianCalendar getCurrentTime(
            @WebParam(partName = "timeZoneId", name = "timeZoneId", targetNamespace = "http://artspb.me/cts")
            String timeZoneId) {
        logger.debug("Operation getCurrentTime was requested.");
        XMLGregorianCalendar gregorianCalendar;
        try {
            gregorianCalendar = getXmlGregorianCalendar(timeZoneId);
        } catch (DatatypeConfigurationException e) {
            throw new RuntimeException(e);
        }
        logger.debug("Successful.");
        return gregorianCalendar;
    }
    private XMLGregorianCalendar getXmlGregorianCalendar(String id) throws DatatypeConfigurationException {
        TimeZone timeZone;
        if (!"".equals(id)) {
            logger.debug("TimeZoneId isn't null: " + id);
            timeZone = TimeZone.getTimeZone(id);
        } else {
            logger.debug("TimeZoneId is null. Will use default value.");
            timeZone = TimeZone.getDefault();
        }
        GregorianCalendar gregorianCalendar = new GregorianCalendar(timeZone);
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar);
    }
}


Now, in accordance with the example , we will add the serviceContext.xml and web.xml files to the resources. Also do not forget about log4j.xml. You can find these files in the archive with source codes, a link to it is given at the end of the article. After that, the implementation of the service can be considered complete, it remains to collect the application and check its operability.

3. Assembly and inspection


To build the project, we will perform the maven "package" task. Deploy the resulting war file on the Tomcat server. We assume that it is available on port 8080.



To check, we use the soapUI program. The WSDL diagram of the service is available at http: // localhost: 8080 / CurrentTimeService / service / currentTimeService? Wsdl , using it we can create a new soapUI project.

We send a request:
PST


We get the answer:
2012-02-02T08:48:24.402-08:00


Instead of a conclusion


The task has been achieved: the web service correctly processes requests. We also managed to avoid a “tight” binding to the generated implementation, which makes the code more flexible and allows you to put less effort into making further changes.

Good luck!

Key links together:

Also popular now: