Developing a Web Service with CXF

0
142
8 min read

In this article we will basically study the sample Order Processing Application and discuss the following points:

  • Developing a service
  • Developing a client

The Order Processing Application

The objective of the Order Processing Application is to process a customer order. The order process functionality will generate the customer order, thereby making the order valid and approved. A typical scenario will be a customer making an order request to buy a particular item. The purchase department will receive the order request from the customer and prepare a formal purchase order. The purchase order will hold the details of the customer, the name of the item to be purchased, the quantity, and the price. Once the order is prepared, it will be sent to the Order Processing department for the necessary approval. If the order is valid and approved, then the department will generate the unique order ID and send it back to the Purchase department. The Purchase department will communicate the order ID back to the customer.

Apache CXF Web Service Development

For simplicity, we will look at the following use cases:

  • Prepare an order
  • Process the order

The client application will prepare an order and send it to the server application through a business method call. The server application will contain a web service that will process the order and generate a unique order ID. The generation of the unique order ID will signify order approval.

In real world applications a unique order ID is always accompanied by the date the order was approved. However, in this example we chose to keep it simple by only generating order ID.

Developing a service

Let’s look specifically at how to create an Order Processing Web Service and then register it as a Spring bean using a JAX-WS frontend.

The Sun-based JAX-WS specification can be found at the following URL: http://jcp.org/aboutJava/communityprocess/final/jsr224/index.html

JAX-WS frontend offers two ways of developing a web service—Code-first and Contract-first. We will use the Code-first approach, that is, we will first create a Java class and convert this into a web service component. The first set of tasks will be to create server-side components.

In web service terminology, Code-first is termed as the Bottoms Up approach, and Contract-first is referred to as the Top Down approach.

To achieve this, we typically perform the following steps:

  • Create a Service Endpoint Interface (SEI) and define a business method to be used with the web service.
  • Create the implementation class and annotate it as a web service.
  • Create beans.xml and define the service class as a Spring bean using a JAX-WS frontend.

Creating a Service Endpoint Interface (SEI)

Let’s first create the SEI for our Order Processing Application. We will name our SEI OrderProcess. The following code illustrates the OrderProcess SEI:


package demo.order;
import javax.jws.WebService;
@WebService
public interface OrderProcess {
@WebMethod
String processOrder(Order order);
}

As you can see from the preceding code, we created a Service Endpoint Interface named OrderProcess. The SEI is just like any other Java interface. It defines an abstract business method processOrder. The method takes an Order bean as a parameter and returns an order ID String value. The goal of the processOrder method is to process the order placed by the customer and return the unique order ID.

One significant thing to observe is the @WebService annotation. The annotation is placed right above the interface definition. It signifies that this interface is not an ordinary interface but a web service interface. This interface is known as Service Endpoint Interface and will have a business method exposed as a service method to be invoked by the client.

The @WebService annotation is part of the JAX-WS annotation library. JAX-WS provides a library of annotations to turn Plain Old Java classes into web services and specifies detailed mapping from a service defined in WSDL to the Java classes that will implement that service. The javax.jws.WebService annotation also comes with attributes that completely define a web service. For the moment we will ignore these attributes and proceed with our development.

The javax.jws.@WebMethod annotation is optional and is used for customizing the web service operation. The @WebMethod annotation provides the operation name and the action elements which are used to customize the name attribute of the operation and the SOAP action element in the WSDL document.

The following code shows the Order class:

package demo.order;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Order")
public class Order {
private String customerID;
private String itemID;
private int qty;
private double price;
// Contructor
public Order() {
}
public String getCustomerID() {
return customerID;
}
public void setCustomerID(String customerID) {
this.customerID = customerID;
}
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}

As you can see, we have added an @XmlRootElement annotation to the Order class. The @XmlRootElement is part of the Java Architecture for XML Binding (JAXB) annotation library. JAXB provides data binding capabilities by providing a convenient way to map XML schema to a representation in Java code. The JAXB shields the conversion of XML schema messages in SOAP messages to Java code without having the developers know about XML and SOAP parsing. CXF uses JAXB as the default data binding component.

The @XmlRootElement annotations associated with Order class map the Order class to the XML root element. The attributes contained within the Order object by default are mapped to @XmlElement. The @XmlElement annotations are used to define elements within the XML. The @XmlRootElement and @XmlElement annotations allow you to customize the namespace and name of the XML element. If no customizations are provided, then the JAXB runtime by default would use the same name of attribute for the XML element. CXF handles this mapping of Java objects to XML.

Developing a service implementation class

We will now develop the implementation class that will realize our OrderProcess SEI. We will name this implementation class OrderProcessImpl. The following code illustrates the service implementation class OrderProcessImpl:

@WebService
public class OrderProcessImpl implements OrderProcess {
public String processOrder(Order order) {
String orderID = validate(order);
return orderID;
}
/**
* Validates the order and returns the order ID
**/
private String validate(Order order) {
String custID = order.getCustomerID();
String itemID = order.getItemID();
int qty = order.getQty();
double price = order.getPrice();
if (custID != null && itemID != null && !custID.equals("")
&& !itemID.equals("") && qty > 0
&& price > 0.0) {
return "ORD1234";
}
return null;
}
}

As we can see from the preceding code, our implementation class OrderProcessImpl is pretty straightforward. It also has @WebService annotation defined above the class declaration. The class OrderProcessImpl implements OrderProcess SEI. The class implements the processOrder method. The processOrder method checks for the validity of the order by invoking the validate method. The validate method checks whether the Order bean has all the relevant properties valid and not null.

It is recommended that developers explicitly implement OrderProcess SEI, though it may not be necessary. This can minimize coding errors by ensuring that the methods are implemented as defined.

Next we will look at how to publish the OrderProcess JAX-WS web service using Spring configuration.

 

Spring-based server bean

What makes CXF the obvious choice as a web service framework is its use of Spring-based configuration files to publish web service endpoints. It is the use of such configuration files that makes the development of web service convenient and easy with CXF.

Spring provides a lightweight container which works on the concept of Inversion of Control (IoC) or Dependency Injection (DI) architecture; it does so through the implementation of a configuration file that defines Java beans and its dependencies. By using Spring you can abstract and wire all the class dependencies in a single configuration file. The configuration file is often referred to as an Application Context or Bean Context file.

We will create a server side Spring-based configuration file and name it as beans.xml. The following code illustrates the beans.xml configuration file:


<beans


xsi_schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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="orderProcess"
implementor="demo.order.OrderProcessImpl"
address="/OrderProcess" />
</beans>

Let’s examine the previous code and understand what it really means. It first defines the necessary namespaces. It then defines a series of <import> statements. It imports cxf.xml, cxf-extension-soap.xml, and cxf-servlet.xml. These files are Springbased configuration files that define core components of CXF. They are used to kick start CXF runtime and load the necessary infrastructure objects such as WSDL manager, conduit manager, destination factory manager, and so on.

The <jaxws:endpoint> element in the beans.xml file specifies the OrderProcess web service as a JAX-WS  endpoint. The element is defined with the following three attributes:

  • id—specifies a unique identifier for a bean. In this case, jaxws:endpoint is a bean, and the id name is orderProcess.
  • implementor— specifies the actual web service implementation class. In this case, our implementor class is OrderProcessImpl.
  • address— specifies the URL address where the endpoint is to be published. The URL address must to be relative to the web context. For our example, the endpoint will be published using the relative path /OrderProcess.

The <jaxws:endpoint> element signifies that the CXF internally uses JAX-WS frontend to publish the web service. This element definition provides a short and convenient way to publish a web service. A developer need not have to write any Java class to publish a web service.

LEAVE A REPLY

Please enter your comment!
Please enter your name here