Chapter 2. Web Services and SOA

In this chapter, we will get into the details of SOA implementation and start practicing in the domain of web services. We will see why XML is the right choice for exchanging messages in an enterprise interoperable environment. Then, starting from a sample set of service definitions, we will follow a top-down methodology to develop our first basic web services. The process will be refined by applying the two commonly used communication protocols (REST and SOAP).

A comparison between the two available styles of web services (RPC and Document) will then be introduced and we will see how the latter is better and widely adopted. In the last section, we will then go through a quick introduction to the most popular web service implementation frameworks.

The SOA Approach

The first step in the path to the SOA is basically the expression of a very simple approach: identifying the business functions that your applications are made of. Let's analyze this phrase in detail:

  • Identifying: is the ability to find and isolate the software parts that provide self-contained and atomic functionalities. This implies designing in a modular way, that is divide ("et Impera", Romans would say) the logics of your problem into small and well defined call specifications. We need to build the boundaries of our software parts and contracts to use them, always keeping in mind that a part that is re-usable in many contexts is sort of a piece of gold. In a sense, we are simply leveraging the concept of "interface" to a more abstract level, the business rule's level.

  • Business functions: refers to the fact that with SOA we are focusing on the model-and-business layer (the M letter in MVC), and not the presentation side (the View and Controller).What we are talking about here is exactly "services". A well-designed service should be agnostic about the specific presentations that it will serve.

  • Applications are made of: a lot of software layers. Here, though, we want to put the emphasis on the "s" of "applications". This is the "big leap" of the SOA approach, going beyond the project we are facing just now, and making a little effort in order to build a thing that will survive the single project and will be eligible to be exploited in a wider scenario, that is, by several applications, and over time.

Now, suppose we have accepted the above methodology and we have also designed the services we need, what are the next steps? How do we implement them?

As a sample service, let's take the one which retrieves the list of all customers. That is a very simple function. It has no input parameters and returns a list of objects.

How is the service consumer (the part of software that makes use of the service, for example, on the User Interface side) expected to invoke the service and receive the list of requested objects?

This can be done in different ways. Among them, the most popular are:

  • With platform native calls: As far as Java is concerned this may be implemented through Remote Method Invocation (RMI), Sockets, Servlets, or JMS.

  • With a distributed object communication middleware: CORBA or DCOM are just some examples.

  • With a text-based communication protocol: This can be done by sending the request as a text stream and obtaining a textual response containing the data. This is the approach on which web services are based.

The first way is straightforward, but it has some drawbacks. It is tied to a common language (the service and its consumer must share the same technology and language — for example Java, .NET). Furthermore, the exchanged object's classes must be the same version otherwise the communication will not happen.

Distributed object communication middleware have been a successful answer for a considerable time span. CORBA in particular, thanks to its cross-platform nature, has offered an evident asset where interoperability was needed.

The text-based approach implies, on the other side, a process of serialization (conversion from object to a textual form) when the client sends the request, and a process of deserialization (conversion from text to object) when received by the server. A similar double process must happen then for the response flow.

The serialization and deserialization processes seem to add complexity to the communication. But consider the advantage, a complete independence from technologies and loose coupling between parts.

The natural way to embed data in a textual form is definitely throughout XML.

XML — Advantages and Disadvantages

The eXtensible Markup Language was designed by the W3C (World Wide Web Consortium) in 1998. It was designed exactly for data exchange purposes and has demonstrated its strength over time.

The advantages that XML provides are significant. In fact, it is:

  • Structured

  • Portable

  • Extensible

  • Text format

XML Pitfalls

The tree-based structure of XML may lead to some apparent problems. A common debate is about the fact that XML is not the best way to represent an arbitrary object because of its limitations when it comes to sharing object references. Think about the previous example. Imagine you have a number of customers in London, with the above representation you would have an overhead of redundant data (a number of identical "city" blocks), which is barely acceptable.

Indeed this example was made just to show a common misuse, where the attribute<city> should be considered as an independent entity, rather than a value.

A better approach would be to handle the problem just like you would do with a relational database that is moving repeated data outside of the main object and embedding just a reference to them in the latter.

With a Stateful approach, the client could have retrieved the list of all "city" entities at a previous stage. So when it calls the getAllCustomers service, this could return just the city ids.

Listing 1 — Stateful Approach
<Customers>
<customer>
<id>4</id>
<name>Smith Ltd</name>
<location>
<address>39, Kensington Rd.</address>
<city>LND</city>
</location>
</customer>
<customer>
<id>7</id>
<name>Merkx & Co.</name>
<location>
<address>39, Venice Blvd.</address>
<city>LAX</city>
</location>
</customer>
...
</Customers>

On the other side, if we want to adopt a Stateless approach, in order to have a self-contained service, we could embed in the response of all the needed lists of data.

Listing 2 — Stateless Approach
<Entireresponse>
<cities>
<city>
<id>LND</id>
<name>London</name>
<country>UK</country>
</city>
<city>
<id>LAX</id>
<name>Los Angeles</name>
<country>USA</country>
</city>
</cities>
<customers>
<customer>
<id>4</id>
...
<location>
...
<city>LND</city>
</location>
</customer>
<customer>
<id>7</id>
...
<location>
...
<city>LAX</city>
</location>
</customer>
...
</customers>
</Entireresponse>

Introduction to Web Services, RESTful Services, and Other Transport with XML

The previous section focused on the advantages that XML adoption brings in SOA implementation, but no mention was made of web services. The terms SOA and web services are sometimes mixed up in the same discussion at the risk of creating some misunderstanding.

SOA is just a methodology, an architectural design choice. It has nothing to do with technology or languages. In "Service Oriented Architecture", the first word is not short for "Web Service"; it is just "Service" in its wider meaning. We can design the service that retrieves the list of all items (or a subset filtered upon criteria) without being involved in the technology implementation choice.

Designing by SOA is, in the end, designing the high-level interfaces of the business rules of a given domain model.

At some point, however, an implementation choice must be made. Therefore, in this paragraph we will explore some solutions, going from a simpler home-made approach, to a complete and widely accepted standard technology (SOAP).

Before going ahead though, it is important to focus on a term that we will use very often in this book.

The term is "protocol" and as we will discover soon, it can be used with different meanings depending on the context. One crucial distinction is between "Transportation (or layer) protocol" and "Communication protocol".

The first refers to the network protocol that transports the information. It may be HTTP (a very common choice), but also may be SMTP (thus allowing asynchronous data exchange) or JMS.

Communication protocol, instead, deals with the way we put and extract the message into and from an XML document, and will be the main subject of this section.

At first, we will see how to build a very basic system where XML requests and responses are exchanged through the HTTP protocol in a homemade manner. This will help understand some communication mechanisms from the ground up.

Then, this approach will be standardized with the REST, getting to a still more basic SOA implementation, but with a clean and well designed communication protocol.

Finally, with SOAP, we will go through a more complete and flexible solution with a wide range of features.

Basic SOA With XML Over HTTP Protocol

The process of designing services yields to a number of results. First of all, it produces a list of service definitions which is sometime referred to as a "Catalog of Services". This, naturally, should not have the form of a flat list, but will be organized into sections or "Functional Domains". So we could have, for example, the "Item", "Order", and "Customer" functional domains. Under these functional domains, the following services can be defined:

Item Functional domains are as follows:

  • insertItem

  • updateItem

  • deleteItemById

  • findItemById

  • findAllItems

  • findItemsByCriteria

Order Functional domains are as follows:

  • createOrder

  • findOrderById

  • findAllOrdersByCustomer

Often there will be the need for some "orthogonal" services. In fact, some services could share common mechanisms, such as a control flow or transaction handling.

Generally, at the beginning of any software design process, a common task is to focus on the basic domain objects and their essential handling operations: Create (or insert), Read (select), Update, and Delete. This is usually referred to as CRUD. No matter which language you are using, which architecture is adopted, all projects virtually have to deal with CRUD actions. In our case, a basic domain object is the Item entity and the first four listed services are exactly the CRUD functions.

Let's begin by analyzing and designing the services that handle the item domain. The insertItem service, for example, could have the following form:

Create

Input

Service

Output

<Item>
<id>0</id>
<code>RX004</code>
<description>
Eth. Cable
</description>
</Item>

=> insertItem =>

<Result>
<retCode>
OK
</retCode>
<id>137</id>
</Result>

The client who wants to use this service in order to insert a new item must provide an XML message with the above input schema. Note that the item id has a zero value, since it is assumed that the server will assign it and return to the client along with a return code.

The other three CRUD actions could be modeled as follows:

Read

Input

Service

Output

<ItemId>
<id>137</id>
</ItemId>

=> findItemById =>

<Item>
<id>137</id>
<code>
RX004
</code>
<description>
Eth. Cable 4 ft.
</description>
</Item>

Update

Input

Service

Output

<Item>
<id>137</id>
<code>RX004</code>
<description>
Eth. Cable 4 ft.
</description>
</Item>

=> updateItem =>

<Result>
<retCode>
OK
</retCode>
<id>137</id>
</Result>

Delete

Input

Service

Output

<ItemId>
<id>137</id>
</ItemId>

=> deleteItem =>

<Result>
<retCode>
OK
</retCode>
<id>0</id>
</Result>

The above design is just an example of the possible communication protocol we can adopt. In fact, in this scenario, without constraints or patterns to follow, we are free to decide the communication protocol. For example, we could find it better to have a unique input-output pattern and a single entry point for all CRUD methods. Here the input is a message with the service name embedded, along with the item object, while the output is composed by a return code and an item object, as described in the following figure.

Generic CRUD Action

Input

Service

Output

<ItemAction>
<method>
findById
</method>
<item>
<id>137</id>
<code></code>
<description>
</description>
</item>
</ItemAction>

=> itemCrudService =>

<ItemActionResponse>
<retCode>OK</retCode>
<item>
<id>137</id>
<code>RX004</code>
<description>
Eth. Cable 4 ft.
</description>
</item>
</ItemActionResponse>

Here the advantage of having a single service for all CRUD actions has a price: we have to provide a partially filled item object (with just the id attribute valued) while invoking the service with findById and delete methods (in fact only the insert and the update methods need to really pass the full-valued item object). On the other hand, having a filled item into the response is meaningful just for the findById method.

However, the CRUD actions do not cover, generally, all the needed services. For instance, in the Item domain, we also need a method that retrieves all the items or at least a subset of them. A possible specification of this service could be the following:

Non-CRUD Action

Input

Service

Output

void input

=> findAllItems =>

<Items>
<item>
<id>137</id>
<code>RX004</code>
<description>
Eth. Cable 4 ft.
</description>
</item>
...
</Items>

So far, we have explored a couple of feasible paths that the service designer may follow. As you noticed, the communication protocol is completely up to you. There are no guidelines, just your skill to abstract concepts.

Once we have settled for the communication protocol (may be one of the above or yet another of your choice), we need to think about the layer protocol and its details. The HTTP protocol is a very practical and flexible solution: we can send the XML message as an HTTP request. This approach is also known as POX-over-HTTP, where POX stands for Plain Old Xml.

In practice, we just need an XML translation library in order to transform the objects written in our programming language into XML documents and vice versa. This is all we need for implementing the services we have described above. But there is more. We can even use different languages for implementing the client and the server side as long as each layer adheres to the defined protocol. The XML document is the key to decoupling parts, as shown in the following figure, where a possible scenario is depicted:

Web Service Decoupling

Web Service Decoupling

A Basic Java Implementation of POX-over-HTTP

Now, to complete the example, we will see how to implement the findById service in the Java language. For the automatic binding, we decided to use the JAXB library. This component is included into the latest Java 6 JDK. So if you use this version of Java you do not need any additional jars. Otherwise, you will have to download JAXB and add it explicitly to your server and client class paths. However, since we will make use of Java Annotations, the following source code requires at least a JDK 5 release in order to be compiled and executed. For the server side service implementation, we adopted Tomcat 5.5. The implementation we are stepping through is in fact made up of a simple Java Servlet.

Let's start with the classes that will be exchanged between the client and the server: Item, ItemAction, and ItemActionResponse. There is very little indeed to say about them; they are basic POJO (Plain Old Java Object) with a Java annotation that has a key role in the process of XML serialization/deserialization.

Listing 3 — XML Binding Annotations

@XmlRootElement(name="Item")

public class Item {
private int id;
private String code;
private String description;
... getter/setter methods omitted ...
@XmlRootElement(name="ItemAction")

public class ItemAction{
private String method;
private Item item;
...
@XmlRootElement(name="ItemActionResponse")

public class ItemActionResponse{
private String retCode
private Item item;
...

The following code represents our main goal: the service implementation. It is implemented in the doPost() method of a Servlet that was mapped with the url-pattern /itemCrudService in the application descriptor web.xml.

Listing 4 — ItemCrudService Server Implementation

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try{
JAXBContext jaxbContext = JAXBContext.newInstance (ItemAction.class, ItemActionResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

//Receiving the XML request and transform it into a Java object
ItemAction itemAction = (ItemAction)
unmarshaller.unmarshal(request.getInputStream());

//Do some action depending on the request content
String method = itemAction.getMethod();
//Prepare the response as a Java object
ItemActionResponse itemActionResponse = new ItemActionResponse();
if ("findById".equals(method)){
int id = itemAction.getItem().getId();
//Retrieve item (e.g. from db)
Item item = new Item();
item.setId(id);
item.setCode("Item XYZ");
item.setDescription("Description item XYZ");
//Fill the response
itemActionResponse.setRetCode("OK");
itemActionResponse.setItem(item);
}
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);

//The following line is not required, it was inserted
//just to see the content of the generated XML message
marshaller.marshal(itemActionResponse, System.out);
//Send the XML message to the client
marshaller.marshal( itemActionResponse,

response.getOutputStream());
}
catch (JAXBException e){
throw new ServletException(e);
}
}

We have just written a basic web service; the flow is clear:

  1. Deserialize the XML request

  2. Do the processing

  3. Prepare and serialize the response

Please note that the above service can be invoked by any language or technology, as long as the process of XML serialization or deserialization is available and the communication protocol is known on the client side.

The Java code for testing the service is as follows:

Listing 5 — ItemCrudService Client Request

//Prepare the request
ItemAction itemAction = new ItemAction();
Item item = new Item();
item.setId(26);
itemAction.setMethod("findById");
itemAction.setItem(item);
//Prepare and establish the connection with the service
URL url = new URL("http://localhost/SoaBookPoxHttp/itemCrudService");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);

//Set the HTTP request method
con.setRequestMethod("POST");
con.connect();
JAXBContext jaxbContext = JAXBContext.newInstance (ItemAction.class, ItemActionResponse.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

//The following line is not required, it was inserted
//just to see the content of the generated XML message
marshaller.marshal(itemAction, System.out);
//Send the XML request to the service
marshaller.marshal(itemAction, con.getOutputStream());
//Get the XML response from the service and deserialize it

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
ItemActionResponse itemActionResponse = (ItemActionResponse)
unmarshaller.unmarshal(con.getInputStream());

//Show the response content
System.out.println("retCode="+itemActionResponse.getRetCode()+ "
" +
"id="+itemActionResponse.getItem().getId()+ "
" +
"code="+itemActionResponse.getItem().getCode()+ "
"+"description="+itemActionResponse.getItem() .getDescription());

As you see, on the client side, it is mandatory to have the visibility of all the classes involved in the communication process (Item, ItemAction, and ItemActionResponse). In this case, where Java is used both for service implementation and client development, these classes were just copied from the server side and dropped into the client project. In general, of course, this is not a requirement (think about using different languages). The only requirement is having objects that fit the serialization or deserialization process.

Using the above approach, in order to implement the findAllItems service, we should create another servlet that does not need to retrieve any input and returns a list of items:

Listing 6 — findAllItems Service Implementation

protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
try {

JAXBContext jaxbContext = JAXBContext.newInstance (ItemList.class, Item.class);

ItemList itemList = new ItemList();
itemList.setList(new ArrayList());
Item i1 = new Item();
i1.set ... ;
itemList.getList().add(i1);
... populate itemList ...

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);

//Just to see the content of the generated XML message
marshaller.marshal(itemList, System.out);
//Send the XML message to the client

marshaller.marshal(itemList, response.getOutputStream());

}
catch (JAXBException e) {
throw new ServletException(e);
}
}

Note that we also need to define the ItemList class:

Listing 7 — ItemList Binding

import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="ItemList")

public class ItemList {
private List list;
...

While the correspondent client code may look like this:

Listing 8 — findAllItems Service Client Request


URL url = new URL("http://localhost/SoaBookPoxHttp/findAllItems");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.connect();

//Void Request
//Get Response

JAXBContext jaxbContext = JAXBContext.newInstance (ItemList.class, Item.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
ItemList itemList = (ItemList)
unmarshaller.unmarshal(con.getInputStream());

for (Iterator iterator = itemList.getList().iterator();
iterator.hasNext();)
{
Item item = (Item) iterator.next();
System.out.println( item.getId()+" - "+ item.getCode()+" - "+
item.getDescription());
}

REST — Exploiting the HTTP Protocol

The Representational State Transfer ( REST) is a web architectural style presented by Roy Fielding back in 2000 in his doctoral thesis. The basic idea of REST is the full exploitation of the HTTP protocol, in particular:

  • It focuses onResources, that is, each service should be designed as an action on a resource.

  • It takes full advantage of all HTTP verbs (not just GET and POST, but also PUT and DELETE).

In the basic POX-over-HTTP example, which we saw previously, you may have noticed that we assumed to use POST as HTTP verb. Although, we listed the source code for just one out of the several services we defined, all of them can be implemented using the same verb (not necessarily POST, any other method will do the job right). Therefore, the idea is, why not exploit this transportation protocol feature to map the usual CRUD and other methods in order to have a clearer communication protocol?

An association between the four CRUD methods and the correspondent HTTP verbs was therefore established and is shown in the following table:

HTTP verb

CRUD action

Action description

POST

CREATE

Save new resources

GET

READ

Read resources

PUT

UPDATE

Modify existing resources

DELETE

DELETE

Delete resources

Keeping in mind that the set of resources, each one with its values, represents the State of the system, the following rules should be applied:

  • The State can be modified by verbs POST, PUT, and DELETE.

  • The State should never change as a consequence of a GET verb.

  • The verb POST should be used to add resources to the State.

  • The verb PUT should be used to alter resources into the State.

  • The verb DELETE should be used to remove resources from the State.

  • The communication protocol should be stateless, that is, a call should not depend on the previous ones.

All this may sound quite interesting, but what exactly is a "resource"? Basically, a resource is a scope within which the four HTTP verbs can cover all requested actions. Take for instance the Item domain we explored earlier. Well, that is a good candidate to be treated as a resource. As you see in the implementation source (Listing 5), a switch was introduced (in the if-then block) to do different actions depending on the method name contained in the request. This conditional flow control can be avoided and its role can be done by the HTTP verbs. Let's see how to do that in practice:

In order to create a new Item (the insertItem service), an XML document containing the object can be sent to the server with the POST method, while the response may be a generic outcome object:

Listing 9 — Outcome Binding


@XmlRootElement(name="Outcome")

public class 
Outcome {
private String retCode;
private String retMessaget;
...
}

The service code will then be kept small and without the conditional flow instructions for the action to be executed (compare with Listing 5):

Listing 10 — REST CREATE Server Implementation

protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
try{
JAXBContext jaxbContext = JAXBContext.newInstance (Item.class, Outcome.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
//Receiving the XML request and transform it into a Java object
Item item = (Item) unmarshaller.unmarshal (request.getInputStream());
System.out.println("Inserting item# "+item.getId());
// ... insert item
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
Outcome outcome = new Outcome();
outcome.setRetCode("OK");
outcome.setRetMessaget("Item was inserted successfully");
marshaller.marshal(outcome, response.getOutputStream());
}
catch (Exception e) {
throw new ServletException(e);
}
}

Please note that the above is a simple homemade implementation of the REST protocol. We decided to use a basic servlet implementation in order to focus on the key concepts of this communication protocol. However, there are several other ways to adopt REST, for example, by using JAX-WS (which will be used next when exploring SOAP) or with Axis 2.

Coming back to our example, the updateItem service can be implemented by analogous source code with the only differences being the servlet method (doPut instead of doPost) and, of course, the inner update action. Indeed, the REST approach would recommend another difference that we will show a little ahead.

For the insert action, here is an example of the client code:

Listing 11 — REST CREATE Client Request

Item item = new Item();
item.set...
//Prepare and establish the connection with the service

URL url = new URL("http://localhost/SoaBookREST/itemService");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);

//Set the HTTP request method

con.setRequestMethod("POST");
con.connect();
JAXBContext jaxbContext = JAXBContext.newInstance (Item.class, Outcome.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

//Send the XML request to the service

marshaller.marshal(item, con.getOutputStream());

//Get the XML response from the service and deserialize it

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Outcome outcome = (Outcome)
unmarshaller.unmarshal(con.getInputStream());

As far as the deleteItem, findItemById, and findAllItems services are concerned, the REST methodology suggests a slightly different communication protocol. In fact, the above actions do not need to upload an XML document. They just have to pass the object's id or nothing at all (in the findAllItems case). In these situations, the called URI, along with the HTTP verb, contains all the information needed to perform the actions. The samples of the REST requests are as shown in the following table:

Verb

URI sample

Action

DELETE

http://localhost/SoaBookREST/itemService/14

Delete item #14

GET

http://localhost/SoaBookREST/itemService/14

Retrieve item #14

GET

http://localhost/SoaBookREST/itemService

Retrieve all items

As you can see, the HTTP request (verb plus URI) tells clearly what is happening, or at least, what is the desired action. Note that now the URI may contain some additional data (the id). So in the web descriptor, we must check to have an URL pattern instead of an exact correspondence:

Listing 12 — servlet Mapping Section in web.xml

<servlet-mapping>
<servlet-name>ItemService</servlet-name>
<url-pattern>/itemService/*</url-pattern>
</servlet-mapping>

Here is the service code for the last two actions:

Listing 13 — REST READ Service Implementation

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try{
if (request.getPathInfo()==null){
//findAllItems

ItemList itemList = new ItemList();
itemList.setList(new ArrayList());
//retrieve all items
...
itemList.getList().add(...);
...
//Send the XML message to the client

JAXBContext jaxbContext = JAXBContext.newInstance (ItemList.class, Item.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(itemList, response.getOutputStream());

} else {
//
findItemById

int id = (new Integer(
request.getPathInfo().substring(1)))
.intValue();
//retrieve item by id (e.g. from a database)
Item item = ...

JAXBContext jaxbContext = JAXBContext.newInstance(Item.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(item, response.getOutputStream());

}
}
catch (Exception e) {
throw new ServletException(e);
}
}

As far as the update action is concerned, the REST style indeed suggests having the object's id in the URI:

PUT http://localhost/SoaBookREST/itemService/14

In fact, this way, the HTTP request is self-explanatory (it reads "update item #14") in accordance with the REST philosophy.

In general, if you need to create other non-CRUD services with the above technology, the choice falls between:

  1. Creating an ad-hoc servlet to be used with an appropriate HTTP verb

  2. Re-using an existing servlet and verb with the introduction of some custom logic in the request composition and parsing

Also consider that passing parameters into the request can be a practical alternative to differentiate the control flow, although REST-purists do not like this approach. So, the request could take the form:

http://localhost/SoaBookREST/itemService?id=14

REST purists may have a point here. In fact, this way we are introducing a dependency on the parameter name (id), and somehow adding complexity to a simple and linear style.

SOAP

The Simple Object Access Protocol (SOAP) is a web service standard communication protocol defined by the W3C. It basically defines the structure of the exchanged message, which is composed of an "envelope" with a "header" and a "body". As you will see next, this protocol adds various levels of complexity. But it also offers a wide range of powerful features, among which are:

  • Automatic generation of classes involved in the communication process

  • Automatic generation of the web service descriptor (WSDL)

  • Automatic generation of client classes starting from the service WSDL

  • Ability to be used with network protocols other than HTTP (for example, SMTP or JMS)

  • Ability to encapsulate authentication mechanisms

  • Ability to establish a stateful conversation

In order to show you a straightforward implementation of the services of our domain sample, we will use the JDK 6 embedded capabilities to define and publish web services. In fact, while in the previous examples we exploited the JAXB component to perform the automatic binding between XML documents and Java objects, here we will make use of the JAX-WS library, which will increase the abstraction level significantly.

Look how easy it is to create a couple of services such as insert and update:

Listing 14 — JAX-WS Annotations

package com.packt.soajava.soap.service.item;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import com.packt.soajava.model.item.Item;
import com.packt.soajava.model.item.Outcome;

@WebService

public class ItemWs {

@WebMethod
public Outcome insert(Item item) {
//Insert item ...
System.out.println("Inserting item "+item.getId());
Outcome outcome = new Outcome();
outcome.setRetCode("OK");
outcome.setRetMessage("Item was inserted successfully");
return outcome;
}

@WebMethod
public Outcome update(Item item) {
//Update item ...
System.out.println("Updating item "+item.getId());
Outcome outcome = new Outcome();
outcome.setRetCode("OK");
outcome.setRetMessage("Item was updated successfully");
return outcome;
}

As you see the abstraction level here allows a compact and neat source code, without any part dealing with the serialization/deserialization process, just the essential service code. The structure of a web service implemented with SOAP is quite different from what we have seen with the other approaches so far. In fact with basic POX-over-HTTP, we had to create several classes (servlets) for a single functional domain (for example, Item domain), while using REST a single class was needed, but only because our designed methods matched well with the four HTTP verbs. With SOAP, we can have as many methods in a web service as we need, and each one is independent from the other in its signature.

Publishing the above service requires some further steps. First of all, we need to generate the classes involved in the communication process. This is performed by the wsgen utility bundled with JDK 6. Just open a command shell, and run the following line:

<JDK6_HOME>in
wsgen -cp <ProjectClassesRoot> 
-d <ProjectSourceRoot>
 -keep com.packt.soajava.soap.service.item.ItemWs

The above command will generate the needed classes into the<ProjectSourceRoot> (-d=destination directory) folder, given the specified full-path ItemWs class and the classpath (-cp). Now, you should find a new package in the project sources (com.packt.soajava.soap.service.item.jaxws), and inside it, there should be four classes. In fact, for each defined web method, two classes will be generated: one with the same name of the method (capitalized) and the other with the same name concatenated with "Response".

The web service is now ready to be published. The JDK 6 makes available, mainly for prototyping usage, a very easy way to do this. Just write and run a class that executes the following line:

Endpoint.publish( "http://localhost:8001/SoaBookSOAP_server/itemWs",
new ItemWs());

We have just published our web service at the specified URI. You may of course change this URI in order to change the URL pattern or port.

How can we check if the service was published correctly? Point your browser to the correspondent WSDL:

http://localhost:8001/SoaBookSOAP_server/itemWs?WSDL

What you are looking at is the automatically generated WSDL (Web Service Definition Language). Its content represents the structure of the service, and it plays a key role when it comes to have the client classes automatically generated.

The latter action can, in fact, be performed by the wsimport utility:

<JDK6_HOME>inwsimport -d <ClientProjectSourceRoot>
-p com.packt.soajava.soap.client.test.item
-keep http://localhost:8001/SoaBookSOAP_server/itemWs?WSDL

With this command the needed classes will be created into the specified client source folder (-d), using the given package name (-p), and retrieving the service structure at the given URI. Among these classes we will find ItemWsService, the client factory of the web service and ItemWs, an interface supported by the service proxy created by the ItemWsService factory.

Now the client code can be as simple as this:

Listing 15 — JAX-WS Sample Client

ItemWsService service = new ItemWsService();

ItemWs itemWs = service.getItemWsPort();

Item item1 = new Item();
item1.set ...
Outcome outcome = itemWs.insert(item1);

Note that any technology that supports SOAP can generate its own client classes with an automatic process, starting from the published web service descriptor (WSDL).

In the end, with the SOAP approach, we can keep a simple and neat code at both ends of the communication process (the web service implementation and the end client), while the hard work is done by the intermediate auto-generated classes.

RPC and Document Based-WS: How to Communicate, Pros and Cons of the Two Approach

We have just seen how SOAP can leverage the developer's work by doing the entire hard job behind the scenes. Indeed, we have not even seen the content of the XML documents that client and server are exchanging. Well, this can be done using a TCP/IP monitor utility (for example, Apache TCPMon).

Monitoring the request content of the client call, shown in listing 15, gives the following results:

Listing 16 — SOAP XML Request

<?xml version="1.0" ?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="http://item.service.soap.soajava.packt.com/">
<soapenv:Body>
<ns1:insert>
<arg0>
<code>XY</code>
<description>xy desc</description>
<id>26</id>
</arg0>
</ns1:insert>
</soapenv:Body>
</soapenv:Envelope>

while the response content is as follows:

Listing 17 — SOAP XML Response

<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:insertResponse
xmlns:ns2="http://item.service.soap.soajava.packt.com/">
<return>
<retCode>OK</retCode>
<retMessage>Item was inserted successfully</retMessage>
</return>
</ns2:insertResponse>
</S:Body>
</S:Envelope>

As you can see, the XML content of a SOAP message is structured as an envelope which contains a mandatory body, while the header is optional. The content of the body element represents the payload that is the exchanged XML document.

However, when dealing with SOAP, a wide range of options are available. In our last example, we just adopted the default settings to keep things simpler and straightforward.

You may have heard, for example, about binding style (RCP or Document) or use (Encoded or Literal) or parameter style (Bare or Wrapped). In this paragraph, we will explore these concepts with particular emphasis on the binding style.

Before getting into this analysis though, we should spend some time on WS-I. The term stands for Web Service — Interoperability and represents a set of standards put together in order to allow the process of exchanging data throughout web services in a heterogeneous environment (for example, between Java and .NET). Of all the combinations of binding style, use, and parameter style, only the following are WS-I compliant, and we will concentrate exactly on them:

  • RPC / literal

  • Document / literal (bare or unwrapped)

  • Document / literal wrapped

The "encoded" value for the use attribute is prohibited by WS-I. With this value, in fact, the data is serialized following the SOAP encoding described in Section 5 of SOAP 1.1 specification. Validating a SOAP encoded message against a WSDL description is quite a hard work, and since the validation is a fundamental step toward interoperability, only the use "literal" is allowed by WS-I.

RPC / Literal

One of the first architectural choices that has to be made when we decide to develop SOAP web services is whether to use RPC or Document binding style. Remote Procedure Call (RPC) is a generic mechanism throughout which is a procedure that resides on a computer (or a virtual machine) can be called by a program running on a different computer (or virtual machine). This paradigm has been around for decades and was implemented by several technologies, among which, the most popular are CORBA, DCOM, and RMI.

Despite the changes in technologies, an RPC call is always characterized by:

  • A remote address

  • A method (or operation) name

  • A sequence of parameters

  • A synchronous response

Note that, aside from the first, it shares the same characteristics of a classic local method call.

What does this old RPC paradigm have to do with SOAP and web services? Well, quite a lot indeed. In fact, in the early days of its definition (before being publicly published), SOAP was designed to support only RPC. It was, in a sense, a standardized evolution of the various distributed programming technologies.

With some modification in the annotation of the web service we designed last, we can switch it to RPC style (the JAX-WS default is "Document") and begin to explore this approach.

Listing 18 — SOAP RPC Style

@WebService
@SOAPBinding(style=SOAPBinding.Style.RPC)

public class ItemWs {
@WebMethod
public Outcome insert(@WebParam(name="itemParam") Item item,
@WebParam(name="categoryParam") String category)
{
//Insert item ...

As you can see we have introduced another parameter, the category, and our goal now is to insert an item into the specified category. We used the @WebParam annotation to give a name to each method argument.

Now, let's publish the service (just run the class with the Endpoint.publish line, the wsgen utility is not required in this case), import the client classes from the published WSDL with wsimport utility, and make a client call:

Outcome outcome = itemWs.insert(item1, "A");

If we monitor the request XML document, we will see the following structure:

Listing 19 — SOAP RPC Request

<soapenv:Body>
<ans:insert xmlns:ans="http:// ... ">
<itemParam>

<code>XY</code>
<description>xy desc</description>
<id>26</id>
</itemParam>

<categoryParam>A</categoryParam>
</ans:insert>

</soapenv:Body>

where we can recognize the typical RCP parts, that are the method name and the sequence of parameters.

The correspondent WSDL (that may be seen throughout the TCP monitor or pointing the browser to the URL (http://localhost:8001/SoaBookSOAP_RPC_server/itemWs?WSDL) is listed here:

Listing 20 — SOAP RPC WSDL

<types>
<xsd:schema>
<xsd:import schemaLocation="http://127.0.0.1:8002/ SoaBookSOAP_RPC_server/itemWs?xsd=1" namespace="http://item.service. soap.soajava.packt.com/"></xsd:import>
</xsd:schema>
</types>
<message name="insert">
<part name="itemParam" type="tns:item"></part>
<part name="categoryParam" type="xsd:string"></part>
</message>
<message name="insertResponse">
<part name="return" type="tns:outcome"></part>
</message>

<portType name="ItemWs">
<operation name="insert" parameterOrder= "itemParam categoryParam">
<input message="tns:insert"></input>
<output message="tns:insertResponse"></output>
</operation>

</portType>
<binding name="ItemWsPortBinding" type="tns:ItemWs">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<operation name="insert">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace= "http://item.service.soap.soajava.packt.com/">
</soap:body>
</input>
<output>
<soap:body use="literal" namespace=
"http://item.service.soap.soajava.packt.com/">
</soap:body>
</output>
</operation>
</binding>
<service name="ItemWsService">
<port name="ItemWsPort" binding="tns:ItemWsPortBinding">
<soap:address location=
"http://127.0.0.1:8002/SoaBookSOAP_RPC_server/itemWs">
</soap:address>
</port>
</service>
</definitions>

The schema location (<xsd:schema> block) is imported from URL:

http://127.0.0.1:8001/SoaBookSOAP_RPC_server/itemWs?xsd=1

and its content is the following:

Listing 21 — SOAP RPC XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://item.service.soap.soajava.packt.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://item.service.soap.soajava.packt.com/" version="1.0">
<xs:element name="Item" type="tns:item"></xs:element>
<xs:element name="Outcome" type="tns:outcome"></xs:element>
<xs:complexType name="item">
<xs:sequence>
<xs:element name="code" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="description" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="id" type="xs:int"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="outcome">
<xs:sequence>
<xs:element name="retCode" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="retMessage" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

</xs:schema>

What should be noted here is that the schema defines only the complex type parameters (Item and Outcome in our case). It does not give any information useful to validate either the other simple parameters, or the rest of the SOAP message. Therefore, a major problem in adopting RPC style is that, the exchanged XML documents cannot be validated against an XML Schema Definition (XSD).

Let's explore the Document style and see if it overcomes this limit.

Document / Literal

This style is also known as Document "bare" or "unwrapped" and we will soon get into the explanation of this term. For the moment the thing to pay attention to is that, using JAX-WS, the default value for the parameter style is "wrapped". Hence, in order to use the Document bare style, we have to set it explicitly.

Listing 22 — SOAP Document style

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT, parameterStyle=SOAPBinding.ParameterStyle.BARE)
public class ItemWs {
@WebMethod
public Outcome insert(@WebParam(name="itemParam") Item item,
@WebParam(name="categoryParam") String category) { ...

Now, if we follow the usual steps in order to call this service from a client (again skipping the wsgen step), we will get an error while importing the client classes from the published WSDL.


error: operation "insert": more than one part bound to body

This is an error that will indeed help us understand the difference between an RPC and a Document approach. What we should know is that WS-I only allows one child in the body of a SOAP message. But what is the reason of such a specification?

The Document style represents a new and different paradigm: the service input is "a document", not a request of the execution of a method with the correspondent parameter value. This means that a single object should be passed, and this object will be the sole input to the web service. The document will contain the information needed to perform its processing, but there is nothing here like a method name or a sequence of parameters. That is the reason why WS-I only allows one child.

Therefore, in order to perform our task (inserting an item into a category) with a Document, using WS-I compliant approach, we should refactor the service. We should create a new object called, for instance, ItemInsertRequest, which wraps the needed information (the item and the category). That is the reason of the name of this style (bare or unwrapped): there is no wrapping object around the parts; it must be created explicitly.

Listing 23 — Request Wrapper

@XmlRootElement(name = "ItemInsertRequest")
public class ItemInsertRequest {
private Item item;

private String category;

...

and the web service refactorized in order to have just one parameter (the document representing the request):

Listing 24 — Web Service Using the Defined Wrapper

@WebMethod
public Outcome insert(
@WebParam(name="itemInsertRequestParam")
ItemInsertRequest itemInsertRequest) {
...

In these conditions we will not get errors while generating the client classes with the wsimport utility, and can finally make the refactorized client call:

Listing 25 — SOAP Document Client Request


ItemInsertRequest req = new ItemInsertRequest();


req.setItem(item1);

req.setCategory("A");
Outcome outcome = itemWs.
insert(req);

that will be forwarded with the following SOAP body:

Listing 26 — SOAP Document XML Request


<ns1:itemInsertRequestParam>
<category>A</category>
<item>

<code>XY</code>
<description>xy desc</description>
<id>26</id>

</item>
</ns1:itemInsertRequestParam>

Please note that, although the structure is indeed the same as with RPC style (see listing 19), we are now dealing with a document instead of a method call while the category and item are no more parameters, but just attributes of this document.

What should be noted instead about the WSDL is that, other than having just one part inside the input message and having the style set to document, the attribute type has gone missing and a correspondent element attribute has taken its place.

Listing 27 — SOAP Document WSDL

<message name="insert">
<part element="tns:itemInsertRequestParam"
name="itemInsertRequestParam"></part>
</message>
...
<binding name="ItemWsPortBinding" type="tns:ItemWs">
<soap:binding style="document"

As far as the XML schema is concerned, it can now be used to validate the entire document:

Listing 28 — SOAP Document XSD

<xs:element name="Item" type="tns:item"></xs:element>
<xs:element name="ItemInsertRequest"
type="tns:itemInsertRequest"></xs:element>
<xs:element name="Outcome" type="tns:outcome"></xs:element>
<xs:element nillable="true" name="insertResponse"
type="tns:outcome"></xs:element>
<xs:element nillable="true" name="itemInsertRequestParam"
type="tns:itemInsertRequest"></xs:element>
<xs:complexType name="itemInsertRequest">
<xs:sequence>
<xs:element name="category" type="xs:string"
minOccurs="0"></xs:element>
<xs:element name="item" type="tns:item"
minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="item">
<xs:sequence>
<xs:element name="code" type="xs:string"
minOccurs="0"></xs:element>
<xs:element name="description" type="xs:string"
minOccurs="0"></xs:element>
<xs:element name="id" type="xs:int"></xs:element>
</xs:sequence>

</xs:complexType>

The main strength of Document/literal style is therefore the ability to allow the validation of the whole XML document exchange.

With this approach, though, we have lost something the operation name is no more present in the SOAP message. This may be a drawback in some situations, take for instance the case where the message is transmitted over an asynchronous TCP/IP protocol such as SMTP. The process of dispatching the message may be difficult, if not impossible.

Another disadvantage of this style is that, if we are dealing with already developed applications, a certain effort has to be taken into account in order to refactor both the server and the client side code.

Document / Literal Wrapped

This style is the default in JAX-WS, and we have already made use of it in our very first SOAP example (see Listing 14). The following annotation is in fact useless with JAX-WS:

Listing 29 — SOAP Document Wrapped Style

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

Now, let's go back to the initial structure of the web service (before the refactoring needed by the Document bare style):

Listing 30 — SOAP Document Wrapped Web Service

@WebMethod
public Outcome insert(@WebParam(name="itemParam") Item item, @WebParam(name="categoryParam") String category) {

and follow the usual steps in order to make a client call (now the wsgen step is required).

Well, now we will not get any error, even if we have more than one parameter, as in RPC style. What does this style do to adhere to the Document style, without forcing us to refactor our source code? It simply wraps (automatically, without our effort) the method name and the parameters into a new object, whose name is the same of the method itself.

In fact, the body of the SOAP message is now in this form:

Listing 31 — SOAP Document Wrapped XML Request

<ns1:insert>
<itemParam>
<code>XY</code>
<description>xy desc</description>
<id>26</id>
</itemParam>
<categoryParam>A</categoryParam>
</ns1:insert>

In conclusion, the Document / literal wrapped style gathers the advantages from both Document and RPC approaches:

  • The SOAP message can be validated against an XML schema

  • The SOAP body contains only one child, and is thus WS-I compliant

  • Multiple parameters are allowed without any refactoring

  • The operation name is contained in the message

It is, in fact, the default when we use JAX-WS and in general a good choice for most cases.

Why We Should Use Doc-WS?

The RPC Inheritance

In the previous paragraph, we introduced the difference between RPC and Document style. At first, one can argue that, after all, examining the exchanged messages and their WSDL, the two approaches are not that different, especially the RPC and Document wrapped ones. Well, in a sense, this is true.

The difference is indeed more philosophical than practical, at least for most of us accustomed for decades to the "method call" paradigm. We may have gone through several programming languages and technologies, but we always could count on a rock pillar that is of being able to call a method (sometimes named "procedure", "function", or whatever) passing a sequence of parameters and (optionally) getting the result.

In this scenario, when SOAP was initially conceived, web services were more or less an extension of this model in order to allow the call of a remote procedure (RPC) in a more standardized fashion. In fact, as mentioned before, the initial SOAP specification was based upon RPC style.

The Document-Oriented Way

Now, we intend to show how the Document approach is shifting the focus for a new programming model that will arguably take the leading way in the future.

A document is similar to a message, that is, something to be "sent" or "forwarded" to a destination which is designed to process it.

Document Style

Document Style

Self-Containing Documents and Asynchronous Models

We should not focus on when this processing will take place, but must instead ensure that the message contains all the information needed for the processing itself. Therefore, the message should be a self-contained business document. This is a fundamental prerequisite when dealing with an asynchronous transportation protocol (for example SMTP or JMS, both supported by SOAP), but is anyway a good practice even when not explicitly required.

Another situation where a self-contained business document is a requirement is when a work-flow system is used. In fact, since the transitions inside a work-flow are intrinsically asynchronous, the Document style fits well in this scenario.

Validating Capabilities

We have already highlighted one intrinsic advantage of this style: the capability to perform a full validation of the exchanged documents against their correspondent XML schemas.

Loose Coupling

One of the major weaknesses of the RPC approach is the tight coupling that it imposes on architectures. A change in a service method signature has an immediate impact throughout the system, forcing the refactoring up to the client layer. With Document style, the problem is drastically reduced since a change in the structure of a message (like, adding a new attribute) does not affect the document exchange mechanisms. On the other hand, a change in a back-end (internal) method signature has generally no effect upon the messages structure.

This loose coupling, intrinsic in the Document style, leads to more robust and reliable architectures that are easier to maintain, and having a modular aspect.

Interoperability

Finally, we have to consider the value of interoperability, which is the ability to work together with different technologies and systems. This can be obtained primarily by adhering to standard communication protocols and directives, with an eye open though, to the market trends. The Document style is gaining consensus and is largely adopted by most vendors. It is a matter of fact that both the Java reference implementation of JAX-WS, along with most other Java WS implementations (see Chapter 6), and the .NET platform use the Document style as the default setting.

Implementations: JAX-WS 2, Axis2, Spring-WS, and XFire/CXF 2.0

In the path towards web services, we need to choose, at some point, the implementation that we intend to adopt. The choice may depend upon a number of factors. In this paragraph, we will examine some of the main implementation focusing on their features and peculiarities in order to make the choice easier.

JAX-WS 2

We have indeed already been introduced to JAX-WS in the previous paragraphs. What should be noted first, about this option, is that it is a specification (JSR-224), rather than an implementation. In fact, its name stands for "Java API for XML Web Services" and it follows the previousJAX-RPC (Java API for XML-based Remote Procedure Call) specification.

One of the main advantages of this choice is that its Reference Implementation is included both into Java SE 6 and Java EE 5. Thus no external library is needed in order to use it. If you adopt this embedded version, then you will be working with the version 2.0 of the product, though, at the time of writing, it has reached version 2.1 as a separate implementation.

As far as the data binding model is concerned, it uses JAXB, while the XML parser engine is the stream-based pull parser StAX (Streaming API for XML). This parsing approach, where the client gets XML data only when requested, allows better performances compared to a DOM-based approach, where the entire XML document is parsed to obtain an in-memory object tree. In fact, not only is the requested memory footprint smaller, but also there is the advantage of having the parser start its process earlier.

JAX-WS supports both SOAP and REST communication protocols, though RESTful services cannot take advantage of the automatic code generation (in contrast with the SOAP/WSDL approach) since a standard for RESTful services description has not yet been defined.

It strongly relies on the usage of annotations and supports a number of transportation protocols, going beyond HTTP including SMTP and JMS.

Moreover the range of WS-* features covered is indeed wide. It goes from WS-Security and Policy to WS-Atomic Transaction and WS-ReliableMessaging.

Finally, among its features, there is also the capability to build Stateful web services.

Axis 2

This tool is part of "Web Service Project @ Apache", a set of several projects that cover various aspects related to the development and usage of web services. They are for the majority implementations of protocols and specifications.

Axis2 is a complete re-factoring of the previous 1.x version, and upon its architecture two different implementations were built, Axis2/Java and Axis2/C.

The SAX event-based XML parser used in the previous version has been replaced by the pull-based StAX, which allows greater control over the document processing that translates into higher efficiency and performances.

Indeed Axis2 uses AXIOM (AXIs Object Model), a light-weight object model for XML processing, which is based on StAX and offers enhancing features.

Axis2 can be used to develop both SOAP-based and RESTful web services. Also, it supports Asynchronous (or Non-Blocking) web services invocation, which is implemented by Callback mechanisms.

It has been designed with a modular and extensible architecture. The processes of sending and receiving the SOAP messages are performed by two "Pipes" (or "Flows"): the In Pipe and Out Pipe. Each pipe is designed to process the message throughout a sequence of phases which can have pluggable "Handlers", there by giving the whole architecture a high-level of extensibility. In fact, in addition to built-in phases, there is the option to add User-defined phases with custom handlers inside them, in order to perform new mechanisms or to override existing ones.

Another important level of Handlers grouping is the concept of Module. Each module defines a set of handlers, and a descriptor of the phase rules. A handler can specify not only the phase where it will perform its action, but also its execution order inside the phase throughout the phase rules. In the Axis2 language, a module is "available" when it is present in the system, though not active. The activation of a module turns it to the "engaged" state, after which its handlers are placed into their associated phases and enabled. Thus, it is easy, for example, to plug-in modules that handle WS-* specifications such as WS-Security (Apache Rampart module) or WS-Atomic Transaction (Apache Kandula2 module).

The data binding is not part of the core of Axis2, but it is provided by an extension mechanism that allows the choice among ABD (AxisData Binding), XMLBeans, JAX-Me, and JibX. Also, the range of the transmission protocols supported is complete (HTTP, TCP, SMTP, and JMS).

The default Axis2 installation procedure consists of deploying the "WAR distribution" to the application server (for Tomcat (the declared recommended container) and just copying the file into the CATALINA_HOME/webapps directory). This will deploy the "axis2" web application (the Axis2 Administration Application) that allows the addition and configuration of services and modules.

Please note that services, modules, phases, and handlers are configured in an independent way with respect to the other deployed web applications. In other words, if you have a set of deployed web applications, each with its own business layer, you will not put a service into one of these web applications. Instead, it will be defined and configured into axis2 application and therefore generally available to every consumer (a client or another server application).

Also consider that every configuration made with the Axis2 Administration Application will not be saved and will therefore be lost after a restart of Axis2 application. Now, the situation will go back to the manually edited configuration files.

Alternatively, you can install the "standard binary distribution", which includes, in addition to all the necessary jars, a number of command line tools for:

  • Generating the Java code from the WSDL file, and vice versa (java2wsdl and wsdl2java).

  • Starting a simple standalone server (axis2server), where you can deploy your services.

  • Starting a java application with the automatic loading of the entire needed library (axis2).

Spring-WS

Spring Framework is certainly one of the more popular and interesting products today available in the Java development area. It has definitely revolutionized the approach to designing software projects. With its aspect-oriented philosophy, and the introduction of the concept of "Inversion of Control (IoC)" or "Dependency Injection", it has made the process of building the architecture of a J2EE application easier and cleaner. But Spring is much more than an IoC container. It provides out-of-the-box patterns and templates, and integrates well with a number of other frameworks and tools, brings flexibility, modularity, and robustness.

This great community has made, among the others, its contribution to the web services area, and its name is "Spring Web Services" or "Spring-WS".

Therefore, an immediate advantage in adopting this framework is the inheritance of the Spring concepts and patterns, as well as, the re-use of the know-how you may have already consolidated. The loose coupling between the service contract (or interface) and its implementation is, for example, one of the first pros of this choice.

A mainstream web service recipe recommends starting the designing from the WSDL (contract-first) rather than from the Java code. Spring-WS pushes this approach further, driving the designer to start from the schemas (XSD) of the input and output XML messages. The WSDL will then be automatically generated from the XSDs.

The XML handling can be configured to use a DOM-based library (W3C DOM, JDOM, dom4j, XOM), SAX, StAX and XPath, while for XML binding, you can choose between JAXB, Castor, XMLBeans, JiBX, and XStream.

Spring-WS has a powerful and flexible Message Dispatcher which can handle the XML message distribution.

Particular care has been dedicated to the WS-Security aspects regarding Authentication, Digital signatures, Encryption, and Decryption.

XFire / CXF

XFire has been developed with the goal of obtaining better performance with respect to Axis 1.x (the de facto standard at that time). In fact, it uses a fast object model based on StAX.

It is simple and easy to use; it provides support for several binding libraries: JAXB, Castor, and XMLBeans. But the default is Aegis Binding — a fast binding mechanism with a small memory requirement.

XFire integrates well with many containers, among which are Spring and PicoContainer (another Inversion-of-Control framework). A set of easy-to-use client API makes it easy to build the client side, and to develop unit tests. The transports supported are HTTP, JMS, and Jabber/XMPP.

Recently, XFire and another web service framework, Celtix, have converged to a new product, CXF 2.0, which should be considered the continuation of XFire 1.x. The goal of this new tool is to go further in the directions of high performances, and ease of use.

CXF supports a number of protocols in addition to SOAP, including REST (via Annotations) and CORBA. It adheres to several standards and WS-* specifications.

Its focus is also on being made embeddable into other programs and pushes on the code-first methodology instead of contract-first.

Summary

In this chapter, we examined the relationship between the SOA methodology and the basics of web service implementation. We saw how XML can be used as the common language to decouple the communication between web services implementations and their consumer clients. From a basic XML-over-HTTP approach to the REST and SOAP protocols, we got into the details of how web services can be implemented with various degrees of complexity and flexibility. Further, while exploring the options of the SOAP protocol, we dissected the difference between adopting an RPC or a Document style. In particular, the Document style showed its advantages over RPC. In fact, it is largely adopted as the default style by the majority of the web service implementation frameworks.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset