您的位置:首页 > 运维架构 > Apache

Developing SOAP Web service using Apache CXF

2015-09-14 03:14 525 查看
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.

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.

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

Document

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

Create a struts2 skeleton application to contain your service.

You can use any MVC framework but I prefer struts2 for my own reasons.

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.

Insert a book in book self

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.

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
.

Add the CXF dependencies as shown in create skeleton application section.

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.

Create a stub SEI in exact same package structure as the parent SEI.

Create BookVO in same package structure as the parent BookVO.

The above classes should be exactly same as you have created in the parent application.

We need not create the SEI implementation at client end.

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);<
acbf
/span>

//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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cxf