March 8, 2008, 4:41 a.m.
posted by max
Designing a Service's Interaction LayerA service's interaction layer has several major responsibilities, and chief among them is the design of the interface the service presents to the client. Since clients access the service through it, the interface is the starting point of a client's interaction with the service. The interaction layer also handles other responsibilities, such as receiving client requests, delegating requests to appropriate business logic, and creating and sending responses. This section examines the responsibilities of the interaction layer and highlights some guidelines for its design. 1 Designing the InterfaceThere are some considerations to keep in mind as you design the interface of your Web service, such as issues regarding overloading methods, choosing the endpoint type, and so forth. Before examining these issues, decide on the approach you want to take for developing the service's interface definition. Two approaches to developing the interface definition for a Web service are: How do these two approaches compare? Starting with Java interfaces and creating a WSDL document is probably the easier of the two approaches. With this approach, you need not know any WSDL details because you use vendor-provided tools to create the WSDL description. While these tools make it easy for you to generate WSDL files from Java interfaces, you do lose some control over the WSDL file creation.
With the Java-to-WSDL approach, it may be hard to evolve the service interface without forcing a change in the corresponding WSDL document, and changing the WSDL might require rewriting the service's clients. These changes, and the accompanying instability, can affect the interoperability of the service itself. Since achieving interoperability is a prime reason to use Web services, the instability of the Java-to-WSDL approach is a major drawback. Also, keep in mind that different tools may use different interpretations for certain Java types (for example, java.util.Date might be interpreted as java.util.Calendar), resulting in different representations in the WSDL file. While not common, these representation variations may result in some semantic surprises. On the other hand, the WSDL-to-Java approach gives you a powerful way to expose a stable service interface that you can evolve with relative ease. Not only does it give you greater design flexibility, the WSDL-to-Java approach also provides an ideal way for you to finalize all service details—from method call types and fault types to the schemas representing exchanged business documents—before you even start a service or client implementation. Although a good knowledge of WSDL and the WS-I Basic Profile is required to properly describe these Web services details, using available tools helps address these issues. After you decide on the approach to take, you must still resolve other interface design details, which are described in the next sections. 1.1 Choice of the Interface Endpoint TypeIn the J2EE platform, you have two choices for implementing the Web service interface—you can use a JAX-RPC service endpoint (also referred to as a Web tier endpoint) or an EJB service endpoint (also referred to as an EJB tier endpoint). Using one of these endpoint types makes it possible to embed the endpoint in the same tier as the service implementation. This simplifies the service implementation, because it obviates the need to place the endpoint in its own tier where the presence of the endpoint is solely to act as a proxy directing requests to other tiers that contain the service's business logic. When you develop a new Web service that does not use existing business logic, choosing the endpoint type to use for the Web service interface is straightforward. The endpoint type choice depends on the nature of your business logic—whether the business logic of the service is completely contained within either the Web tier or the EJB tier:
When you add a Web service interface to an existing application or service, you must consider whether the existing application or service preprocesses requests before delegating them to the business logic. If so, then keep the following guideline in mind:
If the existing application or service does not require preprocessing of the incoming request, choose the appropriate endpoint that is present in the same tier as the existing business logic. Besides these major considerations for choosing an endpoint type, there are other, more subtle differences between an EJB service endpoint and a JAX-RPC service endpoint. You may find it helpful to keep in mind these additional points when choosing a Web service endpoint type:
1.2 Granularity of ServiceMuch of the design of a Web service interface involves designing the service's operations, or its methods. You first determine the service's operations, then define the method signature for each operation. That is, you define each operation's parameters, its return values, and any errors or exceptions it may generate.
For those Web services that implement a business process, the nature of the business process itself often dictates the service's granularity. Business processes that exchange documents, such as purchase orders and invoices, by their nature result in a Web service interface that is coarse grained. With more interactive Web services, you need to carefully choose the granularity of these operations. You should keep the same considerations in mind when designing the methods for a Web service as when designing the methods of a remote enterprise bean. This is particularly true not only regarding the impact of remote access on performance but also with Web services; it is important with Web services because there is an underlying XML representation requiring parsing and taking bandwidth. Thus, a good rule is to define the Web service's interface for optimal granularity of its operations; that is, find the right balance between coarse-grained and fine-grained granularity.
More coarse-grained service operations, such as returning catalog entries in sets of categories, keep network overhead lower and improve performance. However, they are sometimes less flexible from a client's point of view. While finer-grained service operations, such as browsing a catalog by products or items, offer a client greater flexibility, these operations result in greater network overhead and reduced performance.
For example, consolidating logically different operations is inefficient and should be avoided. It is much better to consolidate similar operations or operations that a client is likely to use together, such as querying operations.
If you are planning to expose existing stateless session beans as Web service endpoints, remember that such beans may not have been designed with Web services in mind. Hence, they may be too fine grained to be good Web service endpoints. You should consider consolidating related operations into a single Web service operation. Good design for our airline reservation Web service, for example, is to expect the service's clients to send all information required for a reservation—destination, preferred departure and arrival times, preferred airline, and so forth—in one invocation to the service, that is, as one large message. This is far more preferable than to have a client invoke a separate method for each piece of information comprising the reservation. To illustrate, it is preferable to have clients use the interface shown in Code Figure. 1. Using Consolidation for Greater Efficiency (Recommended)
public interface AirlineTicketsIntf extends Remote {
public String submitReservationRequest(
AirReservationDetails details) throws RemoteException;
}
Code Figure combines logically-related data into one large message for a more efficient client interaction with the service. This is preferable to receiving the data with individual method calls, as shown in Code Figure. 2. Retrieving Data with Separate Method Calls (Not Recommended)
public interface AirlineTicketsIntf extends Remote {
public String submitFlightInformation(FlightDetails fltInfo)
throws RemoteException;
public String submitPreferredDates(Date depart, Date arrive)
throws RemoteException;
// other similar methods
}
However, it might not be a good idea to combine in a single service invocation the same reservation with an inquiry method call. Along with optimal granularity, you should consider data caching issues. Coarse-grained services involve transferring large amounts of data. If you opt for more coarse-grained service operations, it is more efficient to cache data on the client side to reduce the number of round trips between the client and the server. 1.3 Parameter Types for Web Service OperationsA Web service interface exposes a set of method calls to clients. When invoking a service interface method, a client may have to set values for the parameters associated with the call. When you design an interface's methods, choose carefully the types of these parameters. Keep in mind that a method call and its parameters are sent as a SOAP message between the client and the service. To be part of a SOAP message, parameters must be mapped to XML. When received at the client or service end, the same parameters must be mapped from XML to their proper types or objects. This section describes some guidelines to keep in mind when defining method call parameters and return values. Note: Since each call potentially may return a value, the discussion in this section about parameter values applies equally to return values. Parameters for Web service method calls may be standard Java objects and types, XML documents, or even nonstandard types. Whether you use the Java-to-WSDL approach or the WSDL-to-Java approach, each type of parameter must be mapped to its XML equivalent in the SOAP message. Figure shows how the binding happens for various types of parameters. 3. Binding Parameters and Return Values with JAX-RPC
1.3.1 Java Objects as ParametersParameters for Web service calls can be standard Java types and objects. If you use the Java-to-WSDL approach, you specify the parameter types as part of the arguments of the method calls of your Java interface. If you use the WSDL-to-Java approach, you specify the parameter types as the type or element attributes of the part element of each message in your WSDL. The type of a parameter that you use has a significant effect on the portability and interoperability of your service. The platform supports the following Java data types. (Refer to the JAX-RPC specification at http://java.sun.com/xml/jaxrpc/ for the equivalent WSDL mappings for these Java data types.)
As Figure shows, parameters that have standard type mappings are bound implicitly. However, the developer must do more work when using parameters that do not have standard type mappings. See "Handling Nonstandard Type Parameters" on page 76 for more details on using nonstandard Java types and possible side effects of such use. Here are some additional helpful points to consider when you use Java objects with standard type mappings as parameters.
Since the J2EE container automatically handles mappings based on the Java types, using these Java-MIME mappings frees you from the intricacies of sending and retrieving documents and images as part of a service's request and response handling. For example, your service, if it expects to receive a GIF image with a MIME type of image/gif, can expect the client to send a java.awt.Image object. A sample Web service interface that receives an image might look like the one shown in Code Figure: Code Figure. Receiving a java.awt.Image Object
import java.awt.Image;
public interface WeatherMapService extends Remote {
public void submitWeatherMap(Image weatherMap)
throws RemoteException, InvalidMapException;
}
In this example, the Image object lets the container implementation handle the image-passing details. The container provides javax.activation.DataHandler classes, which work with the Java Activation Framework to accomplish the Java-MIME and MIME-Java mappings.
1.3.2 XML Documents as ParametersThere are scenarios when you want to pass XML documents as parameters. Typically, these occur in business-to-business interactions where there is a need to exchange legally binding business documents, track what is exchanged, and so forth. Exchanging XML documents as part of a Web service is addressed in a separate section—see "Handling XML Documents in a Web Service" on page 105 for guidelines to follow when passing XML documents as parameters. 1.3.3 Handling Nonstandard Type ParametersJAX-RPC technology, in addition to providing a rich standard mapping set between XML and Java data types, also provides an extensible type mapping framework. Developers can use this framework to specify pluggable, custom serializers and deserializers that support nonstandard type mappings.
Vendors currently can provide their own solutions to this problem. It must be emphasized that if you implement a service using some vendor's implementation-specific type mapping framework, then your service is not guaranteed to be portable and interoperable.
Instead, a better way is to pass these parameters as SOAP document fragments represented as a DOM subtree in the service endpoint interface. (See Figure.) If so, you should consider binding (either manually or using JAXB) the SOAP fragments to Java objects before passing them to the processing layer to avoid tightly coupling the business logic with the document fragment. 1.4 Interfaces with Overloaded MethodsIn your service interface, you may overload methods and expose them to the service's clients. Overloaded methods share the same method name but have different parameters and return values. If you do choose to use overloaded methods as part of your service interface, keep in mind that there are some limitations, as follows:
Let's see how this applies in the weather service scenario. As the provider, you might offer the service to clients, letting them look up weather information by city name or zip code. If you use the Java-to-WSDL approach, you might first define the WeatherService interface as shown in Code Figure. Code Figure. WeatherService Interface for Java-to-WSDL Approach
public interface WeatherService extends Remote {
public String getWeather(String city) throws RemoteException;
public String getWeather(int zip) throws RemoteException;
}
After you define the interface, you run the vendor-provided tool to create the WSDL from the interface. Each tool has its own way of representing the getWeather overloaded methods in the WSDL, and your WSDL reflects the particular tool you use. For example, if you use the J2EE 1.4 SDK from Sun Microsystems, its wscompile tool creates from the WeatherService interface the WSDL shown in Code Figure. Code Figure. Generated WSDL for WeatherService Interface
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="WeatherWebService" .......>
<types/>
<message name="WeatherService_getWeather">
<part name="int_1" type="xsd:int"/>
</message>
<message name="WeatherService_getWeatherResponse">
<part name="result" type="xsd:string"/>
</message>
<message name="WeatherService_getWeather2">
<part name="String_1" type="xsd:string"/>
</message>
<message name="WeatherService_getWeather2Response">
<part name="result" type="xsd:string"/>
</message>
...
</definitions>
Notice that the WSDL represents the getWeather overloaded methods as two different SOAP messages, naming one getWeather, which takes an integer for the zip code as its parameter, and the other getWeather2, which takes a string parameter for the city. As a result, a client interested in obtaining weather information using a city name invokes the service by calling getWeather2, as shown in Code Figure. 6. Using Weather Service Interface with Java-to-WSDL Approach
...
Context ic = new InitialContext();
WeatherWebService weatherSvc = (WeatherWebService)
ic.lookup("java:comp/env/service/WeatherService");
WeatherServiceIntf port = (WeatherServiceIntf)
weatherSvc.getPort(WeatherServiceIntf.class);
String returnValue = port.getWeather2("San Francisco");
...
For example, to obtain the weather information for San Francisco, the client called port.getWeather2("San Francisco"). Keep in mind that another tool may very likely generate a WSDL whose representation of overloaded methods is different.
If instead you choose to use the WSDL-to-Java approach, your WSDL description might look as follows. (See Code Figure.) 7. WSDL for Weather Service with Overloaded Methods Avoided
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="WeatherWebService" ...>
<types/>
<message name="WeatherService_getWeatherByZip">
<part name="int_1" type="xsd:int"/>
</message>
<message name="WeatherService_getWeatherByZipResponse">
<part name="result" type="xsd:string"/>
</message>
<message name="WeatherService_getWeatherByCity">
<part name="String_1" type="xsd:string"/>
</message>
<message name="WeatherService_getWeatherByCityResponse">
<part name="result" type="xsd:string"/>
</message>
...
</definitions>
Since the messages in a WSDL file must have unique names, you must use different message names to represent methods that you would otherwise overload. These different message names actually convert to different method calls in your interface. Notice that the WSDL includes a method getWeatherByZip, which takes an integer parameter, and a method getWeatherByCity, which takes a string parameter. Thus, a client wishing to obtain weather information by city name from a WeatherService interface associated with the WSDL in Code Figure might invoke the service as shown in Code Figure. 8. Using Weather Service with WSDL-to-Java Approach
...
Context ic = new InitialContext();
WeatherWebService weatherSvc = (WeatherWebService)
ic.lookup("java:comp/env/service/WeatherService");
WeatherServiceIntf port = (WeatherServiceIntf)
weatherSvc.getPort(WeatherServiceIntf.class);
String returnValue = port.getWeatherByCity("San Francisco");
...
1.5 Handling ExceptionsJust like any Java or J2EE application, a Web service application may encounter an error condition while processing a client request. A Web service application needs to properly catch any exceptions thrown by an error condition and propagate these exceptions. For a Java application running in a single virtual machine, you can propagate exceptions up the call stack until reaching a method with an exception handler that handles the type of exception thrown. To put it another way, for non-Web service J2EE and Java applications, you may continue to throw exceptions up the call stack, passing along the entire stack trace, until reaching a method with an exception handler that handles the type of exception thrown. You can also write exceptions that extend or inherit other exceptions. However, throwing exceptions in Web service applications has additional constraints that impact the design of the service endpoint. When considering how the service endpoint handles error conditions and notifies clients of errors, you must keep in mind these points:
A Web service application may encounter two types of error conditions. One type of error might be an irrecoverable system error, such as an error due to a network connection problem. When an error such as this occurs, the JAX-RPC runtime on the client throws the client platform's equivalent of an irrecoverable system exception. For Java clients, this translates to a RemoteException. A Web service application may also encounter a recoverable application error condition. This type of error is called a service-specific exception. The error is particular to the specific service. For example, a weather Web service might indicate an error if it cannot find weather information for a specified city. To illustrate the Web service exception-handling mechanism, let's examine it in the context of the weather Web service example. When designing the weather service, you want the service to be able to handle a scenario in which the client requests weather information for a nonexistent city. You might design the service to throw a service-specific exception, such as CityNotFoundException, to the client that made the request. You might code the service interface so that the getWeather method throws this exception. (See Code Figure.) 9. Throwing a Service-Specific Exception
public interface WeatherService extends Remote {
public String getWeather(String city) throws
CityNotFoundException, RemoteException;
}
Service-specific exceptions like CityNotFoundException, which are thrown by the Web service to indicate application-specific error conditions, must be checked exceptions that directly or indirectly extend java.lang.Exception. They cannot be unchecked exceptions. Code Figure shows a typical implementation of a service-specific exception, such as for CityNotFoundException. 10. Implementation of a Service-Specific Exception
public class CityNotFoundException extends Exception {
private String message;
public CityNotFoundException(String message) {
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
}
Code Figure shows the service implementation for the same weather service interface. This example illustrates how the service might throw CityNotFoundException. 11. Example of a Service Throwing a Service-Specific Exception
public class WeatherServiceImpl implements WeatherService {
public String getWeather(String city)
throws CityNotFoundException {
if(!validCity(city))
throw new CityNotFoundException(city + " not found");
// Get weather info and return it back
}
}
Chapter 5 describes the details of handling exceptions on the client side. (In particular, refer to "Handling Exceptions" on page 230.) On the service side, keep in mind how to include exceptions in the service interface and how to throw them. Generally, you want to do the following:
Although they promote interoperability among heterogeneous platforms, Web service standards cannot address every type of exception thrown by different platforms. For example, the standards do not specify how Java exceptions such as java.io.IOException and javax.ejb.EJBException should be returned to the client. As a consequence, it is important for a Web service—from the service's interoperability point of view—to not expose Java-specific exceptions (such as those just mentioned) in the Web service interface. Instead, throw a service-specific exception. In addition, keep the following points in mind:
As a result, you should avoid directly throwing java and javax exceptions to clients. Instead, when your service encounters one of these types of exceptions, wrap it within a meaningful service-specific exception and throw this service-specific exception back to the client. For example, suppose your service encounters a javax.ejb.FinderException exception while processing a client request. The service should catch the FinderException exception, and then, rather than throwing this exception as is back to the client, the service should instead throw a service-specific exception that has more meaning for the client. See Code Figure. 12. Converting an Exception into a Service-Specific Exception
...
try {
// findByPrimaryKey
// Do processing
// return results
} catch (javax.ejb.FinderException fe) {
throw new InvalidKeyException(
"Unable to find row with given primary key");
}
You should avoid defining service-specific exceptions that inherit or extend other exceptions. For example, if CityNotFoundException in Code Figure extends another exception, such as RootException, then when the service throws CityNotFoundException, methods and properties inherited from RootException are not passed to the client. The stack trace for an exception is relevant only to the current execution environment and is meaningless on a different system. Hence, when a service throws an exception to the client, the client does not have the stack trace explaining the conditions under which the exception occurred. Thus, you should consider passing additional information in the message for the exception. Web service standards make it easier for a service to pass error conditions to a client in a platform-independent way. While the following discussion may be of interest, it is not essential that developers know these details about the J2EE platform's error-handling mechanisms for Web services. As noted previously, error conditions are included within the SOAP messages that a service returns to clients. The SOAP specification defines a message type, called fault, that enables error conditions to be passed as part of the SOAP message yet still be differentiated from the request or response portion. Similarly, the WSDL specification defines a set of operations that are possible on an endpoint. These operations include input and output operations, which represent the request and response respectively, and an operation called fault. A SOAP fault defines system-level exceptions, such as RemoteException, which are irrecoverable errors. The WSDL fault denotes service-specific exceptions, such as CityNotFoundException, and these are recoverable application error conditions. Since the WSDL fault denotes a recoverable error condition, the platform can pass it as part of the SOAP response message. Thus, the standards provide a way to exchange fault messages and map these messages to operations on the endpoint. Code Figure shows the WSDL code for the same weather Web service example. This example illustrates how service-specific exceptions are mapped just like input and output messages are mapped. 13. Mapping a Service-Specific Exception in WSDL
<?xml version="1.0" encoding="UTF-8"?>
<definitions ...>
...
<message name="WeatherService_getWeather">
<part name="String_1" type="xsd:string"/>
</message>
<message name="WeatherService_getWeatherResponse">
<part name="result" type="xsd:string"/>
</message>
<message name="CityNotFoundException">
<part name="CityNotFoundException"
element="tns:CityNotFoundException"/>
</message>
<portType name="WeatherService">
<operation name="getWeather" parameterOrder="String_1">
<input message="tns:WeatherService_getWeather"/>
<output message=
"tns:WeatherService_getWeatherResponse"/>
<fault name="CityNotFoundException"
message="tns:CityNotFoundException"/>
</operation>
</portType>
...
</definitions>
1.6 Use of HandlersAs discussed in Chapter 2, and as shown in Figure, JAX-RPC technology enables you to plug in SOAP message handlers, thus allowing processing of SOAP messages that represent requests and responses. Plugging in SOAP message handlers gives you the capability to examine and modify the SOAP requests before they are processed by the Web service and to examine and modify the SOAP responses before they are delivered to the client. Handlers are particular to a Web service and are associated with the specific port of the service. As a result of this association, the handler's logic applies to all SOAP requests and responses that pass through a service's port. Thus, you use these message handlers when your Web service must perform some SOAP message-specific processing common to all its requests and responses. Because handlers are common to all requests and responses that pass through a Web service endpoint, keep the following guideline in mind:
You cannot store client-specific state in a handler: A handler's logic acts on all requests and responses that pass through an endpoint. However, you may use the handler to store port-specific state, which is state common to all method calls on that service interface. Note also that handlers execute in the context of the component in which they are present.
Also note that handlers work directly on the SOAP message, and this involves XML processing. You can use handlers to pass client-specific state through the message context. (See "Passing Context Information on Web Service Calls" on page 366.)
Use of handlers could potentially affect the interoperability of your service. See the next section on interoperability. Keep in mind that it takes advanced knowledge of SOAP message manipulation APIs (such as SAAJ) to correctly use handlers. To avoid errors, Web service developers should try to use existing or vendor-supplied handlers. Using handlers makes sense primarily for writing system services such as auditing, logging, and so forth. 1.7 InteroperabilityA major benefit of Web services is interoperability between heterogeneous platforms. To get the maximum benefit, you want to design your Web service to be interoperable with clients on any platform, and, as discussed in Chapter 2, the Web Services Interoperability (WS-I) organization helps in this regard. WS-I promotes a set of generic protocols for the interoperable exchange of messages between Web services. The WS-I Basic Profile promotes interoperability by defining and recommending how a set of core Web services specifications and standards (including SOAP, WSDL, UDDI, and XML) can be used for developing interoperable Web services. In addition to the WS-I protocols, other groups, such as SOAPBuilders Interoperability group (see http://java.sun.com/wsinterop/sb/index.html), provide common testing grounds that make it easier to test the interoperability of various SOAP implementations. This has made it possible for various Web services technology vendors to test the interoperability of implementations of their standards. When you implement your service using technologies that adhere to the WS-I Basic Profile specifications, you are assured that such services are interoperable. Apart from these standards and testing environments, you as the service developer must design and implement your Web service so that maximum interoperability is possible. For maximum interoperability, you should keep these three points in mind:
WSDL supports two types of messaging styles: rpc and document. The WSDL style attribute indicates the messaging style. (See Code Figure.) A style attribute set to rpc indicates a RPC-oriented operation, where messages contain parameters and return values, or function signatures. When the style attribute is set to document, it indicates a document-oriented operation, one in which messages contain documents. Each operation style has a different effect on the format of the body of a SOAP message. 14. Specifying WSDL Bindings
<?xml version="1.0" encoding="UTF-8"?>
<definitions .......>
<binding name="WeatherServiceBinding" type="tns:WeatherService">
<operation name="getWeather">
<input>
<soap:body use="literal"
namespace="urn:WeatherWebService"/>
</input>
<output>
<soap:body use="literal"
namespace="urn:WeatherWebService"/>
</output>
<soap:operation soapAction=""/></operation>
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http" />
</binding>
<service .....>
</definitions>
Along with operation styles, WSDL supports two types of serialization and deserialization mechanisms: a literal and an encoded mechanism. The WSDL use attribute indicates which mechanism is supported. (See Code Figure.) A literal value for the use attribute indicates that the data is formatted according to the abstract definitions within the WSDL document. The encoded value means data is formatted according to the encodings defined in the URI specified by the encodingStyle attribute. Thus, you can choose between an rpc or document style of message passing and each message can use either a literal or encoded data formatting.
Code Figure shows a snippet from the WSDL document illustrating how the sample weather service specifies these bindings. It is important to keep in mind these message styles and bindings, particularly when you design the interface using the WSDL-to-Java approach and when you design the WSDL for your service. When you use the Java-to-WSDL approach, you rely on the vendor-provided tools to generate the WSDL for your Java interfaces, and they can be counted on to create WS-I-compliant WSDL for your service. However, note that some vendors may expect you to specify certain options to ensure the creation of a WS-I-compliant WSDL. For example, the J2EE 1.4 SDK from Sun Microsystems provides a wscompile tool, which expects the developer to use the -f:wsi flag to create the WS-I-compliant WSDL for the service. It is also a good idea to check the WSDL document itself to ensure that whatever tool you use created the document correctly. Regarding the second issue, you should note that the WS-I Basic Profile 1.0 (which is the profile supported by the J2EE 1.4 platform) does not address attachments. The section, "Parameter Types for Web Service Operations" on page 72, which discussed Java-MIME type mappings provided by the J2EE platform, advised that an efficient design is to use these mappings to send images and XML documents within a completely Java environment. Because the WS-I Basic Profile, version 1.0 does not address attachments, a Web service that uses these mappings may not be interoperable with clients on a non-Java platform.
Since most Web services rely on an exchange of business documents, and interoperability is not always guaranteed, it is important that you properly understand the options for handling XML documents. The section, "Exchanging XML Documents" on page 107, explains the various options available to Web services for exchanging XML documents in an interoperable manner. It should also be noted that the next version of the WS-I Basic Profile specification addresses a standard way to send attachments, and later versions of the J2EE platforms will incorporate this. Last is the issue of handlers. Handlers, which give you access to SOAP messages, at the same time impose major responsibilities on you.
This ends the discussion of considerations for designing a Web service interface. The next sections examine other responsibilities of the interaction layer, such as receiving and delegating requests and formulating responses. 2 Receiving RequestsThe interaction layer, through the endpoint, receives client requests. The platform maps the incoming client requests, which are in the form of SOAP messages, to method calls present in the Web service interface.
As noted in "Parameter Types for Web Service Operations" on page 72 and elsewhere, Web service calls are basically method calls whose parameters are passed as either Java objects, XML documents (javax.xml.transform.Source objects), or even SOAP document fragments (javax.xml.soap.SOAPElement objects).
You may have to undertake additional steps to handle XML documents that are passed as parameters. These steps, which are best performed in the interaction layer of your service, are as follows:
A design such as this helps to catch errors early, and thus avoids unnecessary calls and round-trips to the processing layer. Figure shows the recommended way to handle requests and responses in the Web service's interaction layer. 4. Web Service Request Processing![]() The Web service's interaction layer handles all incoming requests and delegates them to the business logic exposed in the processing layer. When implemented in this manner, the Web service interaction layer has several advantages, since it gives you a common location for the following tasks:
It is generally advisable to do all common processing—such as security checks, logging, auditing, input validation, and so forth—for requests at the interaction layer as soon as a request is received and before passing it to the processing layer. 3 Delegating Web Service Requests to Processing LayerAfter designing the request preprocessing tasks, the next step is to design how to delegate the request to the processing layer. At this point, consider the kind of processing the request requires, since this helps you decide how to delegate the request to the processing layer. All requests can be categorized into two large categories based on the time it takes to process the request, namely:
Note: When referring to request processing, we use the terms synchronous and asynchronous from the point of view of when the client's request processing completes fully. Keep in mind that, under the hood, an asynchronous interaction between a client and a service might result in a synchronous invocation over the network, since HTTP is by its nature synchronous. Similarly, SOAP messages sent over HTTP are also synchronous. The weather information service is a good example of a synchronous interaction between a client and a service. When it receives a client's request, the weather service must look up the required information and send back a response to the client. This look-up and return of the information can be achieved in a relatively short time, during which the client can be expected to block and wait. The client continues its processing only after it obtains a response from the service. (See Figure.) 5. Weather Information Service Interaction
A Web service such as this can be designed using a service endpoint that receives the client's request and then delegates the request directly to the service's appropriate logic in the processing layer. The service's processing layer processes the request and, when the processing completes, the service endpoint returns the response to the client. (See Figure.) 6. Synchronous Interaction Between Client and Service
Code Figure shows the weather service interface performing some basic parameter validation checks in the interaction layer. The interface also gets required information and passes that information to the client in a synchronous manner: 15. Performing a Synchronous Client Interaction
public class WeatherServiceImpl implements
WeatherService, ServiceLifecycle {
public void init(Object context) throws JAXRPCException {....}
public String getWeather(String city)
throws CityNotFoundException {
/** Validate parameters **/
if(!validCity(city))
throw new CityNotFoundException(....);
/** Get weather info form processing layer and **/
/ **return results **/
return (getWeatherInfoFromDataSource(city));
}
public void destroy() {....}
}
Now let's examine an asynchronous interaction between a client and a service. When making a request for this type of service, the client cannot afford to wait for the response because of the significant time it takes for the service to process the request completely. Instead, the client may want to continue with some other processing. Later, when it receives the response, the client resumes whatever processing initiated the service request. Typically in these types of services, the content of the request parameters initiates and determines the processing workflow—the steps to fulfill the request—for the Web service. Often, fulfilling a request requires multiple workflow steps. The travel agency service is a good example of an asynchronous interaction between a client and a service. A client requests arrangements for a particular trip by sending the travel service all pertinent information (most likely in an XML document). Based on the document's content, the service performs such steps as verifying the user's account, checking and getting authorization for the credit card, checking accommodations and transportation availability, building an itinerary, purchasing tickets, and so forth. Since the travel service must perform a series of often time-consuming steps in its normal workflow, the client cannot afford to pause and wait for these steps to complete. Figure shows one recommended approach for asynchronously delegating these types of Web service requests to the processing layer. In this architecture, the client sends a request to the service endpoint. The service endpoint validates the incoming request in the interaction layer and then delegates the client's request to the appropriate processing layer of the service. It does so by sending the request as a JMS message to a JMS queue or topic specifically designated for this type of request.
7. Asynchronous Interaction Between Client and Service
Validation ensures that a request is correct. Delegating the request before validation may result in passing an invalid request to the processing layer, making error tracking and error handling overly complex. After the request is successfully delegated to the processing layer, the service endpoint may return a correlation identifier to the client. This correlation identifier is for the client's future reference and may help the client associate a response that corresponds to its previous request. If the business logic is implemented using enterprise beans, message-driven beans in the EJB tier read the request and initiate processing so that a response can ultimately be formulated. Figure shows how the travel agency service might implement this interaction, and Code Figure shows the actual code that might be used. 16. Implementing Travel Agency Service Interaction
public class ReservationRequestRcvr {
public ReservationRequestRcvr() throws RemoteException {....}
public String receiveRequest(Source reservationDetails) throws
RemoteException, InvalidRequestException{
/** Validate incoming XML document **/
String xmlDoc = getDocumentAsString(reservationDetails);
if(!validDocument(xmlDoc))
throw new InvalidRequestException(...);
/** Get a JMS Queue and delegate the incoming request **/
/** to the queue **/
QueueConnectionFactory queueFactory =
serviceLocator.getQueueConnectionFactory(....);
Queue reservationRequestQueue =
serviceLocator.getQueue(...);
QueueConnection connection =
queueFactory.createQueueConnection();
QueueSession session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
QueueSender queueSender = session.createSender(queue);
TextMessage message = session.createTextMessage();
message.setText(xmlDoc);
queueSender.send(message);
/** Generate and return a correlation identifier **/
return generateCorrelationID();
}
}
8. Travel Agency Service Interaction![]() In Figure, the vertical lines represent the passage of time, from top to bottom. The vertical rectangular boxes indicate when the entity (client or service) is busy processing the request or waiting for the other entity to complete processing. The half arrow type indicates asynchronous communication and the dashed vertical line indicates that the entity is free to work on other things while a request is being processed. One question remains: How does the client get the final result of its request? The service may make the result of the client's request available in one of two ways:
Often this is decided by the nature of the service itself. For example, if the service runs a business process workflow, the workflow requires the service to take appropriate action after processing the request. 4 Formulating ResponsesAfter you delegate the request to the business logic portion of the application, and the business logic completes its processing, you are ready for the next step: to form the response to the request.
This permits having a common location for response assembly and XML document transformations, particularly if the document you return to the caller must conform to a different schema from the internal schema. Keeping this functionality near the endpoint lets you implement data caching and avoid extra trips to the processing layer. (See Figure.). 9. Web Service Response Processing![]() Consider response generation from the weather information service's point-of-view. The weather information service may be used by a variety of client types, from browsers to rich clients to handheld devices. A well-designed weather information service would render its responses in formats suitable for these different client types. However, it is not good design to have a different implementation of the service's logic for each client type. Rather, it is better to design a common business logic for all client types. Then, in the interaction layer, transform the results per client type for rendering. It is thus important to consider the above guidelines, especially when your service has a common processing logic but potentially has different response rendering needs to fit its varied client types. |
- Comment






