Enterprise Java

Developing SOAP Web service using Apache CXF

In last post I walked through the steps for developing a simple RESTFull service using apache CXF.  In this post I will be talking about developing SOAP web service using CXF. Before moving forward let us understand few of the concepts/elements which makes up a SOAP web service

SOAP or Simple Object Access Protocol 

SOAP is a protocol for exchanging XML-based messages over the network using application protocols like http, smtp, etc as carrier. SOAP message comprises of a SOAP envelope. The envelope can be broken into a header and a body. Header contains context related definitions like security while the body contains actual application data. A typical SOAP message looks like

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header>
  </soap:Header>
  <soap:Body>
    <m:GetStockPrice xmlns:m="http://www.example.org/stock">
      <m:StockName>IBM</m:StockName>
    </m:GetStockPrice>
  </soap:Body>
</soap:Envelope>

WSDL or Web Services Description Language

WSDL is a standard based XML Language which is used to describe a web service. A WSDL completely describes what public interface an web service exposes, what parameter it expects, structure of output it returns, location of web service. A WSDL defines a web service as collection of communication end points that are capable of exchanging messages. These communication end points are called ports. Port are composed of two parts.

  1. Contains the public interface exposed by the web service. The interface contains all the methods, parameter needed to invoke them and response structure returned by them.
  2. The second part binds the public interface to network protocol like http. The binding comprises of information like location of the public interface and message format for the service.

SOAP communication styles

There exists two types of communication styles

  1. Document
  2. RPC

The communication style used by SOAP web service is defined in its WSDL.

In the Document style the application data which is part of soap body is sent as XML document. This document can be validated completely by a xml schema which is also part of WSDL. As XML can contain structure as per wish of service developer hence the responsibility of marshaling and unmarshaling xml payload lies at end of provider and consumer code.

In RPC style as the name suggests the consumer invokes the methods of service as if he were invoking a local method. To facilitate this the RPC message consists of list of public interface methods that a consumer can invoke. These methods are listed by names as xml elements.  The method parameters needed by these method forms sub elements of  the method element. The responisibility of marshaling/unmarshaling lies with the web service framework. The framework contains its own marshaling/unmarshaling libraries. RPC style results in tightly coupled code between application code and the web service framework, hence norm is create document style services. With Key concepts in place let see an example of how to write a soap web service using Apache CXF.

Getting the source code for this tutorial

I have committed the source files for this tutorial in SVN.

Note: Both are ItelliJ maven projects so you can directly import them to your intelliJ IDE or copy over the files manually to other IDEs

Create a struts2 skeleton application to contain your service.

You can use any MVC framework but I prefer struts2 for my own reasons. You can see an example of how to create an empty struts2 application in eclipse using maven here.

Add CXF dependencies 

In your project POM add following dependencies to download CXF jars

<properties>
       <cxf.version>2.5.0</cxf.version>
</properties>
<dependencies>
       <!-- apache cxf -->
        <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-frontend-jaxrs</artifactId>
          <version>${cxf.version}</version>
       </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
</dependencies>

For example let us create a simple book shelf web service. For simplicity let us assume following use case.

  1. Insert a book in book self
  2. Retrieve a book from book shelf by title.

Developing the service

This can be done in two ways Code first and contract first. We will be using the code first approach.

Creating a Service Endpoint Interface (SEI)

Let us create a SEI interface called BookShelfService

package com.aranin.weblog4j.services;

import com.aranin.weblog4j.vo.BookVO;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface BookShelfService {

    @WebMethod
    public  String insertBook(BookVO bookVO);
    @WebMethod
    public  BookVO getBook(String title);
}

If you look at the above SEI you can tell that it is a normal java interface with exception of two annotation

  • @WebService – This is an annotation JAXWS library. It turns a normal POJO into a webservice. In our case the annotation is placed right above the interface definition and it notifies that BookShelfService is not a normal interface rather an webservice interface or SEI. There are other attributes to this annotation that can completely define the webservice but we will not be using it right now.
  • @WebMethod – This annotation is optional and is mainly used to provide a name attribute to the public method in wsdl.

Implementing the service. 

Now we have our SEI so let us implement the methods in the interface in our BookShelfServiceImpl

package com.aranin.weblog4j.services;

import com.aranin.weblog4j.hashdb.HashDB;
import com.aranin.weblog4j.vo.BookVO;

import javax.jws.WebService;

@WebService(endpointInterface = "com.aranin.weblog4j.services.BookShelfService",
		serviceName="bookShelfService")
public class BookShelfServiceImpl implements BookShelfService {
    public String insertBook(BookVO bookVO) {
        HashDB.insertBook(bookVO);
        return "Book with name : " + bookVO.getBookName() + " is now available on the shelf";  //To change body of implemented methods use File | Settings | File Templates.
    }

    public BookVO getBook(String title) {

        return HashDB.getBook(title);  //To change body of implemented methods use File | Settings | File Templates.
    }
}

This class is a simple POJO implementing the SEI. Only notable thing here is the @WebService annotation. If you look at it closely we have provided the fully qualified class name of the SEI it implements and name of the webservice.

Data Binding class (BookVO)

package com.aranin.weblog4j.vo;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;

@XmlRootElement(name = "Book")
public class BookVO implements Serializable {

    private long bookId;
    private String bookName;
    private String author;

    public long getBookId() {
        return bookId;
    }

    public void setBookId(long bucketId) {
        this.bookId = bookId;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

The only thing to note here is the @XmlRootElement annotation. This annotation is part of JAXB library. CXF uses JAXB as default data binding component. As BookVO needs to be transported as XML during the webservice calls hence it needs to marshalled/unmarshalled by the JAXB engine in the CXF installation. Using @XmlRootElement annotation we help JAXB in mapping the BookVO class to an xml with its name attribute as root element of the xml.

Spring Based Server Bean

What makes CXF a first rate choice as webservice framework is that it publishes its service endpoints via a spring based configuration file. Lets create a  the configuration file and register our service in it. We will name the file as beans.xml and save it in WEB-INF folder of our application

<?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">

<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />	

<jaxws:endpoint
       id="bookShelfService"
       implementor="com.aranin.weblog4j.services.BookShelfServiceImpl"
       address="/bookshelfservice" />

</beans>

Now to load the beans.xml we simply add following in web.xml

<context-param>
<param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/beans.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>

Finally we need to wire spring and CXF through web.xml.

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

<servlet-mapping>
	<servlet-name>CXFServlet</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

Note: I have not included loading of Spring ContextLoaderListner. If you create a struts2 application via maven using struts2 starter archetype then spring is downloaded and registered by maven project itself.

Now your webservice is ready. Compile and deploy the application in any servlet container. If everything is good then you can see your wsld on following location: http://localhost:8080/weblog4jdemo/bookshelfservice?wsdl

Create your client

There are many tools which can be used to generate client code using the wsdl. To save you further trouble we will utilize CXF’s own front end apis. So let us look at the steps.

  1. Create a simple maven project using IDE of your choice. I am using IntelliJ currently and it is awesome. Lets say name of the project is DemoClient.
  2. Add the CXF dependencies as shown in create skeleton application section.
  3. Since we know what the SEIs and public method and binding objects are. We will create them in the client side to save us trouble. In case there are many such classes we can use tools like wsdl2java etc to generate our code.
  4. Create a stub SEI in exact same package structure as the parent SEI.
  5. Create BookVO in same package structure as the parent BookVO.
  6. The above classes should be exactly same as you have created in the parent application.
  7. We need not create the SEI implementation at client end.
  8. Now we will create a client using JaxWsProxyFactoryBean. This class is a factory which works with the SEI proxies to invoke web service methods. Here is the class.
package com.aranin.weblog4j.client;

import com.aranin.weblog4j.services.BookShelfService;
import com.aranin.weblog4j.vo.BookVO;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class DemoClient {
    public static void main(String[] args){
        String serviceUrl = "http://localhost:8080/weblog4jdemo/bookshelfservice";
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setServiceClass(BookShelfService.class);
		factory.setAddress(serviceUrl);
		BookShelfService bookService = (BookShelfService) factory.create();

        //insert book
        BookVO bookVO = new BookVO();
        bookVO.setAuthor("Issac Asimov");
        bookVO.setBookName("Foundation and Earth");

        String result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        bookVO = new BookVO();
        bookVO.setAuthor("Issac Asimov");
        bookVO.setBookName("Foundation and Empire");

        result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        bookVO = new BookVO();
        bookVO.setAuthor("Arthur C Clarke");
        bookVO.setBookName("Rama Revealed");

        result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        //retrieve book

        bookVO = bookService.getBook("Foundation and Earth");

        System.out.println("book name : " + bookVO.getBookName());
        System.out.println("book author : " + bookVO.getAuthor());

    }
}

Here is the output of above calls

INFO: Creating Service {http://services.weblog4j.aranin.com/}BookShelfServiceService from class com.aranin.weblog4j.services.BookShelfService
result : Book with name : Foundation and Earth is now available on the shelf
result : Book with name : Foundation and Empire is now available on the shelf
result : Book with name : Rama Revealed is now available on the shelf
book name : Foundation and Earth
book author : Issac Asimov

Process finished with exit code 0

There are tons of other stuff you can explore in Apache CXF like Creating dynamic clients, interceptors, leveraging other transport protocol, webservice over https etc. But I intend this post as getting started tutorial.

Phew this is a long post again. I need to improve my writing skills to shorten the length. But still I hope that you enjoyed it and found it useful. I intend to write about a javascript client for webservices in my next post. Until then goodbye and happy coding.
 

Reference: Developing SOAP Web service using Apache CXF from our JCG partner Niraj Singh at the Weblog4j blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

26 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Neo Lite
Neo Lite
11 years ago
Balu
Balu
10 years ago

Very good post Neeraj!!!

Niraj Singh
10 years ago

Thanks Guys,

I am glad you found it useful.

Regards
Niraj

Ken
Ken
10 years ago

This is nicely done. I learned more from this post than I learned reading one of the Packt books on the subject. Just one question: Are you planning to provide more post on CXF development. Some treatments on messaging , filters and interceptors will be really be helpful.

Niraj Singh
10 years ago
Reply to  Ken

Hi Ken,

Thanks for the encouraging comment :-). I do intend to write more on the subject. Lately finding less and less time to devote to blogging. I will drop a comment here once I write something on CXF.

Regards
Niraj

Ken O.
Ken O.
10 years ago
Reply to  Niraj Singh

I find this article to be very refreshing. I almost gave up on CXF for lack of clarity in the books and article on how to use CXF as application development framework. Is there any way to get more articles that show how to take existing Java web application and demonstrate how to convert the api to web service using CXF. I am interested in both SOAP and REST implementations of CXF.

srinivas
srinivas
10 years ago

Hi,
Its very helpful article for Beginners like me.
I’m trying to execute the above and I’m strucked at class BookShelfServiceImpl is using HashDB class/interface. which is not having code snippet. can please place or add to complete this example.

Thanks in advance.

-Srinivas

Niraj Singh
10 years ago
Reply to  srinivas

Hi Srinivas,

Thanks for kind comment. You can download the code from following SVN location http://subversion.assembla.com/svn/weblog4j/Weblog4jDemo/trunk. It will have the hashDB Class.

Regards
Niraj

Dmitry
Dmitry
6 years ago
Reply to  Niraj Singh

The link isn’t available as for now. It would be good if you add the lost class to the post.

Satinder SINGH
Satinder SINGH
5 years ago
Reply to  Dmitry

Hi. Very informative article. Thanks for posting it. But unfortunately, the above link to subversion does not seem to work. I wonder if it is still active in 2019. Thanks.

Raj
Raj
10 years ago

Hi,
really nice blog for beginners like me to start.
am not able to find a jar file containing META-INF/cxf/cxf-extension-soap.xml
I am trying this with latest apache cfx 3.0.1. Do i need to replace it with META-INF/cxf/cxf-extension-jaxws.xml Please let me know thanks.

Gorantla
Gorantla
9 years ago

Its simple but great. Thanks for posting the article.

Rajesh D
Rajesh D
9 years ago

Article explained in clear manner, i found it very useful.

Ami
Ami
9 years ago

I see that in addition to http://localhost:8080/weblog4jdemo/bookshelfservice?wsdl being active
http://localhost:8080/weblog4jdemo/bookShelfService?wsdl (which maps to servicename on Impl) is also active. Additionally if an interceptor was added only calling the CXF endpoint(bookshelfservice) would invoke it.Calling the endpoint with servicename(from Impl) will not invoke it. Any explanation?

Wojciech Zaręba
Wojciech Zaręba
9 years ago
Niraj Singh
9 years ago

Hi Wojciech,

Apologies for the same. The article was written long time ago. I need to find the sources myself :-). Please give me some time, I can push it to github.

Regards
Niraj

AJ
AJ
9 years ago
Reply to  Niraj Singh

Hi Niraj – Can you please find the sources and publish them on github.

AnonyMous
AnonyMous
8 years ago

Nice post

danang
danang
8 years ago

where example client on web ?

electrician
8 years ago

My developer іѕ trying to persuade me to move tο .net
from PHP. I hаve ɑlways disliked tһe idea bесause of the expenses.

But he’s tryiong none tҺе less. ӏ’ve bᥱen usіng Movable-type οn various websites
for аbout ɑ year and am anxious аbout switching to another platform.
Ӏ have ɦeard great thingѕ about blogengine.net.
Is there a way I can transfer ɑll mу wordpress
content into it? Any kind of helρ ԝould Ƅe ցreatly appreciated!

Maria Cristina Ortiz
Maria Cristina Ortiz
7 years ago

Hi,
I’m so grateful for this post, it was simply and make me understand CXF.
Nice job! Keep going, i’ll follow you.

srinivas
srinivas
6 years ago

hi unable to create wsdl file after compiling the above code.could you please help me in this

shakti
shakti
6 years ago

Hi,
I am looking for an example, in which I can generate SOAP Web Service from WSDL.

Plz advise

vishnu dixit
vishnu dixit
6 years ago

it is not working for me (may be it’s mistake in copy past….)

Padm
Padm
5 years ago

Very Helpful content ..
thanks man.!

Vijay
Vijay
5 years ago

Where is the applicationContext.xml file?

Back to top button