Friday, April 28, 2017

Creating a SOAP web service with Apache CXF and Spring

In this example, I will show you how to use Apache CXF together with Spring to create a simple SOAP web service which returns hard-coded user information.

In Eclipse create a new Maven project as below.
Go to File -> New -> Maven Project
Check the check box "Create a simple project(skip archetype selection)".
Click "Next".
Set below parameters.
Group Id : com.example
Artifact Id : CxfSoapExample
Packaging : war

Click "Finish".

You will see in project explorer that a project named "CxfSoapExample" has been created.
Open the pom.xml file.
You may see an error message in pom.XML file as below because you have no web.XML file created yet.
"web.xml is missing and is set to true"

This message will vanish as soon as you created the web.xml file. However, if this message is annoying you can right click on "Deployment Descriptor" node and click "Generate deployment descriptor stub" to create the web.xml file.

Ok, Now let's go back to the pom.xml file. In this tutorial. I am using CXF 3.1.4 and java 1.7. So add those properties and CXF dependencies into the pom.xml file.
My final pom.xml file looks like below.

<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>com.example</groupId>
<artifactId>CxfSoapExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<cxf.version>3.1.4</cxf.version>
<spring.version>4.3.0.RELEASE</spring.version>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
</dependency>
</dependencies>
</project>

Now right click on the project and select "Maven -> Update Project". In the popup window select the "CxfSoapExample" project and click "OK".

Now we are going to create below three java components.
1. UserService.java  - This is an interface in which we define the web service methods
    package example.cxf.service;

    import javax.jws.WebMethod;
    import example.cxf.data.User;

    public interface UserService {
@WebMethod
public User getUser(String requestedBy);
    }

2. UserServiceImpl.java - This is the implementation of UserService interface and will act as the actual service class.
    package example.cxf.service;

    import example.cxf.data.User;

    public class UserServiceImpl implements UserService {

@Override
public User getUser(String requestedBy) {
User user = new User();
user.setFirstName("John");
user.setLastName("Williams");
user.setAge(50);
user.setRequestedBy(requestedBy);
return user;
}
    }

3. User.java - This is just a java class which has variables and methods to store and access user information.

    package example.cxf.data;

    public class User {
private String firstName;
private String lastName;
private String requestedBy;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getRequestedBy() {
return requestedBy;
}
public void setRequestedBy(String requestedBy) {
this.requestedBy = requestedBy;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
    }

Now in order to expose our service lets register it in beans.XML file.
Create a file in webapp/WEB-INF folder and name it as beans.xml.
Open the newly created file and add below content.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">

<jaxws:endpoint
       id="userService"
       implementor="example.cxf.service.UserServiceImpl"
       address="/userService" />

</beans>

Create the web.xml file in webapp/WEB-INF folder(If you haven't created yet) and add below content.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>CxfSoap2</display-name>
  <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  <context-param>
<param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/beans.xml</param-value>
</context-param>

<servlet>
       <servlet-name>CXF-SERVLET</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXF-SERVLET</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Now run the project in tomcat server.
You should be able to see the WSDL file generated for this service by visiting below link.

http://localhost:8080/CxfSoapExample/userService?wsdl

Below is a sample request and response retrieved from SOAP-UI for above service.