web services in action - himalay majumdar

50
Web Services in Action Web services are an important component in the J2EE platform, as they provide for loosely-coupled communication between enterprise systems. They are ideal for Enterprise Application Integration (EAI), particularly those systems that have evolved over time. Design and Architecture The two principal Web service models -- a document-oriented model and a Remote Procedure Call-oriented model -- from which the synchronous and asynchronous Web service architectures are derived Some of the issues to be considered for designing a Web service interface, including granularity of services, the Java API for XML-based Remote Procedure Call (JAX-RPC), and object-centric and document-centric parameter binding. Guidelines on how to architect a Web service is based on receiving and responding to requests, delegating to business logic, and exposing a Web service. When to use? Before you even begin to design a Web service, you should decide whether you need a Web service solution for your application. Web services should be used when you need interoperability across heterogeneous platforms. That is, when you need to expose all or part of your application to other applications on different platforms. Implementing a Web service makes sense when your application's clients are potentially non-J2EE applications. Even if your application's clients are all J2EE applications, you may still want to use Web services if your clients are scattered across the Web. However, when clients are all J2EE applications, it may be best to use J2EE technologies and avoid the extra performance cost of a Web

Upload: himalay-majumdar

Post on 12-Nov-2014

1.702 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Web Services in Action - Himalay Majumdar

Web Services in Action

Web services are an important component in the J2EE platform, as they provide for loosely-coupled communication between enterprise systems. They are ideal for Enterprise Application Integration (EAI), particularly those systems that have evolved over time.

Design and ArchitectureThe two principal Web service models -- a document-oriented model and a Remote Procedure Call-oriented model -- from which the synchronous and asynchronous Web service architectures are derived

Some of the issues to be considered for designing a Web service interface, including granularity of services, the Java API for XML-based Remote Procedure Call (JAX-RPC), and object-centric and document-centric parameter binding. Guidelines on how to architect a Web service is based on receiving and responding to requests, delegating to business logic, and exposing a Web service.

When to use?Before you even begin to design a Web service, you should decide whether you need a Web service solution for your application. Web services should be used when you need interoperability across heterogeneous platforms. That is, when you need to expose all or part of your application to other applications on different platforms.

Implementing a Web service makes sense when your application's clients are potentially non-J2EE applications. Even if your application's clients are all J2EE applications, you may still want to use Web services if your clients are scattered across the Web. However, when clients are all J2EE applications, it may be best to use J2EE technologies and avoid the extra performance cost of a Web service. Keep in mind that one of the key advantages to using Web services technologies is the ability to go through firewalls.

Generic Web servicesGeneric Web services follow the service-oriented architecture model shown in Figure 1.1. In this model, a Web service first publishes its interface to a registry. The client then looks up, or discovers, the Web service from the registry. Last, the client binds to the Web service in order to use its services. In a Java programming environment, the Web service uses the Java API for XML Registries (JAXR) to publish itself to the registry. The client uses the same JAXR API to look up the service in the registry. The client uses JAX-RPC to bind to and use the Web service. See Figure 1.1.

Page 2: Web Services in Action - Himalay Majumdar

Figure 1.1 Publish-Discover-Bind Model

While this architecture showcases generic Web services, when the service provider and the client are known to each other, they can bypass publish and discover steps of the process. Instead, they can directly bind with each other and directly use each other's services. This document looks at scenarios in which the service provider and the client know each other. So no JAXR needed.

Key to Web service design is how a Web service processes requests at the server side (its processing model) and how clients invoke and use the service (the Web service's interaction model). Figure 1.2 shows the categorization of Web services according to their interaction and processing models. Notice that typical Web services mix the different interactions and processing models, along with synchronous and asynchronous communication.

Figure 1.2 Web Service Models

Page 3: Web Services in Action - Himalay Majumdar

A service's processing model may be business object (or method) centric or it may be document centric. The business object-centric approach is driven by a series of method calls. These method calls apply the business logic of the service to a set of business objects containing the information required for processing the request. An example of an object-centric service might be a credit card authorization Web service. Such a service may receive the credit card details as parameters with the method calls. The methods invoked on the service map directly to specific business logic. The method parameters are used to map to a particular business object (such as a session or entity object) or they are used to pass data to the business logic.

With a document-centric Web service, the business logic is kept separate from the document content. The service receives an XML document, and that document contains only data and no explicit binding to the business logic that is to be applied. There is no mapping of the request to the business logic; that is, specific methods are not invoked on the service. Instead, the Web service applies its business logic to the XML document, and the document content determines the processing workflow. A travel agency Web service is a good example of a document-centric service. The service receives a request: an XML document that contains the details of the desired travel itinerary -- dates, places to visit, preferred accommodations, and so forth. The travel agency service processes the request according to the document content.

The interaction model encompasses the client's interaction with the Web service. A client's interaction with a Web service can be synchronous or asynchronous, or a combination of both types of communication. (That is, some method invocations may be synchronous and others may be asynchronous.) When a synchronous model is followed, the application typically uses an RPC-oriented interaction. With this type of interaction, the client's request is mapped to a method call on the Web service's business logic on the server. Using the credit card service as an example, the client utilizes an RPC call to invoke a method on the credit card service's server. The client passes the method the credit card details as an argument. The client might invoke a method to authorize use of the credit card and pass the method an object containing the card details, such as by invoking the method authorizeCreditCard(CreditCard cardDetails).

Document-centric processing is usually associated with an asynchronous messaging communication. The client's request is sent as a message. The Web service receives the message and processes it, sending the results when it completes its processing. In the case of the travel agency service, the details of the client's travel request are sent to the service as an XML document via a message (or as an attachment to an RPC call). The service receives the document and parses it to determine how to process the request.

The RPC-oriented and document-oriented Web services form two ends of a spectrum. At one end, a Web service may use a totally RPC-oriented interaction model and object-centric processing, in which case you model it as a RPC-oriented Web service. At the other end, a service may be completely document oriented and communicate with asynchronous messaging.

Page 4: Web Services in Action - Himalay Majumdar

However, keep in mind that most Web services fall somewhere between these two cases and you can mix and match the models. Keep in mind, also, that even a purely RPC-oriented Web service uses XML protocol (Simple Object Access Protocol), though it keeps the use of XML transparent to the client and server. The client and server deal with method calls and objects as parameters to these calls. The underlying platform handles the XML.

1.2 Web Service Interaction Architectures

There are two principal architectures for Web service interfaces: synchronous Web services and asynchronous Web services. These two architectures are distinguished by their request-response handling. With synchronous services, clients invoke a request on a service and then suspend their processing while they wait for a response. With asynchronous services, clients initiate a request to a service and then resume their processing without waiting for a response.

A Web service may combine synchronous and asynchronous architectures. Often, this architectural decision is made based on the types of work the service performs and the available technologies.

Synchronous Web Services

A credit card service, such as one that might be used in an e-commerce application, is a good example of a synchronous service. The client cannot continue it’s processing until the transaction completes, and obtaining credit approval is a prerequisite to completing the transaction. A stock quote Web service is another example of a synchronous service.

Figure 1.3 Synchronous Web Service Interaction

Page 5: Web Services in Action - Himalay Majumdar

Synchronous Web services are architected using a JAX-RPC servlet endpoint. The servlet endpoint receives the client's request and then delegates the request to the service's appropriate business logic, which may reside in the service's Web tier or Enterprise JavaBeansTM (EJBTM) tier.

Figure 1.4 Synchronous Services with JAX-RPC

Asynchronous Web Services

With asynchronous services, the client invokes the service but does not -- or cannot -- wait for the response. Often, with these services, the client does not want to wait for the response because it may take a significant amount of time for the service to process the request. The client can continue with some other processing rather than wait for the response. Later, when it does receive the response, it resumes whatever processing initiated the service request.

Generally, a document-oriented approach is used for asynchronous class of services.

Figure 1.5 Asynchronous Web Service Communication

Page 6: Web Services in Action - Himalay Majumdar

Developers can begin the design of a Web service interface with either a Java service definition or Web Services Description Language (WSDL) definition. It is usually more convenient to start the design of the Web service interface with a Java service definition instead of a WSDL interface.

Generally, the model you choose for your Web service should be driven by the processing requirements. If you decide to use an object-oriented approach, then it is recommended to use JAX-RPC to invoke methods and pass arguments and return values with a Java objects-to-XML binding to ensure maximum interoperability.

At the other end of the spectrum, such as for business-to-business interaction requirements, you may model a service that follows a document-centric interaction and processing model as a document-oriented Web service. In this model, pass documents in JAX-RPC as javax.xml.transform.Source objects.

Object-Centric Parameter Binding

Figure 1.7 shows how a service endpoint might pass SOAP requests as a parameter to business logic. (The approaches shown within the dotted lines are not recommended.)

Figure 1.7 Binding Parameters and Return Values in Object-Centric Processing

Document-Centric Parameter Binding

Figure 1.8 shows how requests can be passed as parameters or attachments and handled with document-centric processing. Here, the XML document is wrapped into a Source object (javax.xml.transform.Source) and passed to the next level. It is also possible to pass an URL to the XML source document. In addition to the Source object argument, other JAX-RPC arguments may be used to pass metadata, processing requirements, security information, and so forth.

Page 7: Web Services in Action - Himalay Majumdar

Figure 1.8 Parameter and Return Value Binding with Document-Centric Processing

Implementing a Web Service

Once you know how to model your Web service and the design approach you want to take, then you are ready to implement the service. The key steps for implementing a Web service are:

Receiving a document and generating a response Mapping calls to internal representations Performing business logic Exposing the Web service

Performing Business Logic

The EJB tier or business layer is where the business logic is applied to a Web service request. A Web service exists to expose an application's functionality. It typically does not influence the business logic processing. This is particularly true for Web services using an object-centric approach. However, there are some guidelines for performing business logic for Web services with document-centric processing.

It is a good practice to keep an enterprise bean's document manipulation logic separate from the business logic.

With document-centric processing, business logic is applied to data accessed through XML documents. Thus, an enterprise bean must read and modify an XML document to apply the business processing. Abstracting document manipulation logic from business logic allows the bean's developer to switch between different XML document manipulation approaches, such as DOM, SAX, JDOM, and so forth, without affecting the business logic. In addition, it completely hides document processing implementation details from the business logic. This is similar to the Data Access Object (DAO) pattern, which abstracts database access code from the bean's business logic.

Page 8: Web Services in Action - Himalay Majumdar

In the document-centric processing model, an enterprise bean receives an XML document that contains all information for processing a request. Typically, the XML document has well-defined segments containing details about a specific entity.

Rather than pass the entire document to different components, it's best if the receiving bean breaks the document into fragments and passes only the required fragments to other components that implement portions of the business logic.

Designing for Performance

Good design and proper use of the technologies can greatly improve Web service performance. You should consider the following performance recommendations when designing a Web service.

1.4.5.1 Using Caching and Service Granularity

Web service clients tend to be richer clients and thus can do more work on the client side, such as caching. Web services can maximize performance by correctly using data caching. You should consider using caching in a Web service when the service's requested information is primarily read only or when that information changes at a slower rate than at which it is requested.

Caching at the client side may also be effective when the service's granularity of operation is more coarse grained than that of the client requestor. (See Granularity of Web Services.) In such a situation, the service provides more information than the client needs for a particular request. However, if the client issues similar requests, then caching the data may improve response time. This is especially true for clients making synchronous requests, since they must consider the time to construct the response in addition to the time to transfer the data.

On the other hand, fine-grained Web services transfer smaller sets of data but may handle more requests within the same time frame. The amount of time to handle the SOAP protocol, including parsing the XML document request and constructing the XML response, becomes critical, and caching may be useful on the server side. This is especially true when the service exposes fine-grained operations to distributed applications but internally handles coarse-grained requests. Consider caching on the server the SOAP request and response to the Web service itself (with SOAP message handlers) and any internal requests and responses between the Web tier and the EJB tier.

1.4.5.2 Using XML

XML, while it has many benefits, also has performance disadvantages. XML often demands a great deal of CPU processing. Most XML documents must not only be parsed but also validated, and many require additional processing. Processing XML documents

Page 9: Web Services in Action - Himalay Majumdar

also requires a large amount of memory. Typically, XML processing may require creating large numbers of objects, especially when handling document object models of any kind. XML may also be network intensive. A given document may be the aggregation of different external entities. Parsing the document may require that each entity be retrieved across the network.

The following guidelines help minimize the performance overhead of using XML.

Use XML judiciously. Use XML when you must interoperate with heterogeneous systems and provide loosely-coupled integration points. Try to rely on XML protocols such as those implemented by JAX-RPC. Maximize interoperability by using existing public vertical schemas. Avoid using XML for unexposed interfaces or for exchanges between components that are tightly coupled.

Avoid unnecessary parsing and validation. Because processing XML documents may be CPU, network, and memory expensive, it's best to keep to a minimum such operations. You should parse incoming XML documents only when the request is properly formulated, such as documents passed as Source parameters to JAX-RPC calls. Validate the document's meta information, which may have been passed as additional JAX-RPC arguments, and perform the security validation before retrieving the document. Always try to use the proper API to process the document.

Bind documents to domain Java objects as soon as possible. Then process the Java objects rather than the XML documents.

Additional guidelines apply when implementing an application that spans multiple containers. When the application components interact remotely, try to pass only Java objects. Also consider using the Transfer Object design pattern. With remote interaction, it is expensive to pass DOM trees, plus not all implementations support Java serialization of DOM trees. While using serialized XML is expensive and thus best avoided, it may be required to provide loosely-coupled integration points.

Page 10: Web Services in Action - Himalay Majumdar

Creating Web Services

Developing a Web service using JAX-RPC is surprisingly easy. The service itself is basically two files, an interface that declares the service’s remote procedures and a class that implements those procedures.

Runtime is when a program is running (or being executable). That is, when you start a program running in a computer, it is runtime for that program. In some programming languages, certain reusable programs or "routines" are built and packaged as a "runtime library." These routines can be linked to and used by any program when it is running.

public class Runtimeextends Object

Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.

Web services overview

The Web services wizard generates files for the Requestor and the Provider. The Web services wizard supports a number of servers and run-times. Figure shows a list of run-times being shipped with Rational Application Developer.

Rational Application Developer run-times and servers

Artifacts that the Web services wizard generates

The wizard generates three sets of artifacts: 1) The Web service Requestor-side artifacts including the Proxy Bean, 2) the WSDL file, and 3) the Web service Provider-side files. A Web service can be based on a number of different types including a Java bean, Enterprise Java Bean (EJB) component, DADX document, and so on.

Page 11: Web Services in Action - Himalay Majumdar

Starting from a WSDL file (Top Down or Client scenario) or from a Java file (Bottom Up scenario).

Bottom Up Web services scenario

You can start at different points in the wizard and create a Web service using different file types. One start point is with a Java Bean. The Web services wizard would then generate the Requestor-side files including the proxy bean, the WSDL file, and Provider-side files. This is known as the Bottom Up

Top Down scenario

You can also start with a WSDL file and generate the Requestor-side artifacts and the Provider artifacts including a skeleton bean with the WSDL operations. The implementation is left to you to fill in. This is known as the Skeleton or Top Down Scenario.

Page 12: Web Services in Action - Himalay Majumdar

The following interface definition is a simple example showing the methods a wholesale coffee distributor might want to make available to its prospective customers. Note that a service definition interface extends java.rmi.Remote and its methods throw a java.rmi.RemoteException object.

package coffees; import java.rmi.Remote; import java.rmi.RemoteException; public interface CoffeeOrderIF extends Remote {   public Coffee [] getPriceList()                   throws RemoteException;   public String orderCoffee(String coffeeName, int quantity)                  throws RemoteException; }

The method getPriceList returns an array of Coffee objects, each of which contains a name field and a price field. There is one Coffee object for each of the coffees the distributor currently has for sale. The method orderCoffee returns a String that might confirm the order or state that it is on back order.

The following example shows what the implementation might look like (with implementation details omitted). Presumably, the method getPriceList will query the company's database to get the current information and return the result as an array of Coffee objects. The second method, orderCoffee, will also need to query the database to see if the particular coffee specified is available in the quantity ordered. If so, the implementation will set the internal order process in motion and send a reply informing the customer that the order will be filled. If the quantity ordered is not available, the implementation might place its own order to replenish its supply and notify the customer that the coffee is backordered.

package coffees; public class CoffeeOrderImpl implements CoffeeOrderIF {   public Coffee [] getPriceList() throws RemoteException; {    . . .  }   public String orderCoffee(String coffeeName, int quantity)                  throws RemoteException; {    . . .  }}

Page 13: Web Services in Action - Himalay Majumdar

Web Services Clients

We will now turn our attention from providing web services to consuming them. Writing the client application for a Web service entails simply writing code that invokes the desired method. Of course, much more is required to build the remote method call and transmit it to the Web service, but that is all done behind the scenes and is invisible to the client.

The method getPriceList will block until it has received a response and returned it. Because a WSDL document is being used, the JAX-RPC runtime will get the service endpoint from it. Thus, in this case, the client class does not need to specify the destination for the remote procedure call. When the service endpoint does need to be given, it can be supplied as an argument on the command line. Here is what a client class might look like:

package coffees; public class CoffeeClient {  public static void main(String[] args) {    try {       CoffeeOrderIF coffeeOrder = new         CoffeeOrderServiceImpl().getCoffeeOrderIF();      Coffee [] priceList =               coffeeOrder.getPriceList():      for (int i = 0; i < priceList.length; i++) {        System.out.print(priceList[i].getName() + " ");        System.out.println(priceList[i].getPrice());      }    } catch (Exception ex) {     ex.printStackTrace();    }   } }

Invoking a Remote Method

Once a client has discovered a Web service, it can invoke one of the service's methods. The following example makes the remote method call getPriceList, which takes no arguments. As noted previously, the JAX-RPC runtime can determine the endpoint for the CoffeeOrder service (which is its URI) from its WSDL description. If a WSDL document had not been used, you would need to supply the service's URI as a command line argument. After you have compiled the file CoffeeClient.java, here is all you need to type at the command line to invoke its getPriceList method.

java coffees.CoffeeClient

The remote procedure call made by the previous line of code is a static method call. In other words, the RPC was determined at compile time. It should be noted that with JAX-RPC, it is also possible to call a remote method dynamically at run time. This can be done using either the Dynamic Invocation Interface (DII) or a dynamic proxy.

Page 14: Web Services in Action - Himalay Majumdar

HelloIF.java - the service definition interface HelloImpl.java - the implementation class for the HelloIF interface config.xml - a configuration file read by the xrpcc tool, which creates the stub

and tie classes web.xml - a deployment descriptor for the Web component (a servlet) that

dispatches to the service HelloClient.java - the remote client that contacts the service and then invokes

the sayHello method

http://www.ibm.com/developerworks/webservices/library/ws-javaclient/index.html

Web services standards for Java

Page 15: Web Services in Action - Himalay Majumdar

The development of Java technology standards occurs through Java Specification Requests (JSRs) being submitted to the Java Community Process (JCP). Two JSRs cover the Java Web services architecture:

1. JSR 101: Java API for XML based RPC (JAX-RPC)2. JSR 109: Implementing Enterprise Web services.

Both specifications provide conformance and interoperability requirements for vendors' implementations.

JAX-RPC

JAX-RPC defines a simple and easy-to-use Java Application Programming Interface (API) for XML-based Remote Procedure Calls (RPC) and the Java to XML and XML to Java mapping:

WSDL to Java and Java to WSDL mappings: For example, a WSDL port type is mapped to a Java Service Endpoint Interface (SEI).

XML data type to Java data type and Java data type to XML data type mappings, including simple types, complex types, and arrays.

In addition to XML mappings, JAX-RPC also defines the client-side programming model and API, which I will cover in more details in later sections. JAX-RPC 1.1 adds interoperability requirements based on the Web Services Interoperability organization (WS-I) Basic Profile version 1.0.

JSR 109

JSR 109 specifies the Web services programming model and architecture for the Java 2 Enterprise Edition (J2EE) environment. JSR 109 builds on SOAP 1.1 and WSDL 1.1 to cover the use of JAX-RPC in a J2EE environment (Figure 2). It also defines a deployment model to J2EE application servers. JSR 109's client-side programming model, which I will cover in sections below, is conformant to JAX-RPC.

Page 16: Web Services in Action - Himalay Majumdar

Figure 2. JSR 109 and JAX-RPC

JAX-RPC 1.1 and JSR 109 are part of J2EE 1.4.

Service lookup

There are two families of clients, which differ in the way the code is written, packaged, and invoked:

1. Unmanaged clients2. J2EE container-managed clients.

Here, unmanaged means not J2EE container-managed. These are Java 2 Standard Edition (J2SE) clients and are invoked with a simple java command. For unmanaged clients, the service lookup is through the JAX-RPC ServiceFactory, a factory for the creation of instances of services access points. For J2EE container-managed clients, service lookup is through JNDI lookup.

JAX-RPC ServiceFactory

The JAX-RPC ServiceFactory is an abstract class which acts as a factory for instantiating JAX-RPC Services. It is vendor independent and lets you write portable code.

javax.xml.rpc.Service service =

ServiceFactory.newInstance().createService(...);

You need to pass the fully qualified name of the Web service, that is namespace plus service name, to the createService() method and optionally the URL of the WSDL document describing the Web service you want to look up. The steps are as follows:

ServiceFactory

JSR 101: "The JAX-RPC ServiceFactory is the standard way to look up Web services in a J2SE environment."

Page 17: Web Services in Action - Himalay Majumdar

1. Optionally, specify the WSDL URL.2. Specify the Web service's fully qualified name.3. Invoke ServiceFactory's createService() method.

The Service Interface obtained is then used to get a stub, dynamic proxy, or DII Call object, as described in the "Service access" section. Also covered in that section is the Dynamic Invocation Interface (DII). With this method, you do not need to know the WSDL URL of the Web service you want to invoke, and you only specify the service name parameter to the createService() method. Listing 1 shows how to use the ServiceFactory to instantiate a JAX-RPC Service. QName is a javax.xml.namespace.QName.

Listing 1. Using the JAX-RPC ServiceFactory to obtain a JAX-RPC ServiceString wsdlURL = http://localhost:6080/HelloWebService/services/Hello?wsdl";String namespace = "http://Hello.com";String serviceName = "HelloWebService";QName serviceQN = new QName(namespace, serviceName); ServiceFactory serviceFactory = ServiceFactory.newInstance();/* The "new URL(wsdlURL)" parameter is optional */Service service = serviceFactory.createService(new URL(wsdlURL), serviceQN);

JNDI service lookup

J2EE container-managed clients are packaged into Enterprise Archives (.EAR) files and run from inside a J2EE container. In addition to the Java code, descriptors are also packaged into the archive. Several different types of J2EE container-managed clients are:

Application client container clients Web container clients: JavaBean or Servlet EJB container clients: EJB

JAX-RPC defines the programming model for unmanaged clients, whereas JSR 109, "Implementing Enterprise Web services", defines the programming model for J2EE container-managed clients. One of the goals of JSR 109 is that its client programming model is compatible with JAX-RPC. However, JSR 109 does not recommend the use of the JAX-RPC ServiceFactory. It recommends clients use Java Naming and Directory Interface (JNDI) instead to obtain a Service Interface. This is a two step process, also illustrated in Listing 2:

JNDI lookup

JSR 109: "JNDI lookup is the standard way to look up Web services in a J2EE environment."

Page 18: Web Services in Action - Himalay Majumdar

1. Instantiate a local JNDI Context.2. Do a JNDI lookup for the Web service name in this context.

Listing 2. JNDI service lookup

Context ic = new InitialContext();

Service service = (Service) ctx.lookup("java:comp/env/service/HelloService");

The name of the Web service, in this case java:comp/env/service/HelloService, is specified in the client application's deployment descriptor. JSR 109 recommends that all service reference logical names be organized under the service sub-context. With the client environment context being java:comp/env, you end up with:

service name in context = client environment context + "service" subcontext + service name.

In this case, the service name in context is:

java:comp/env/ + service/ + HelloService.

service subcontext + service name (for example, service/HelloService) is also called the logical service name and is declared in the Web service client application's deployment descriptor.

The JNDI lookup returns a JAX-RPC Service Interface. The J2EE container makes sure an implementation of the generic JAX-RPC Service is bound at the location specified in the deployment descriptor. You can also cast the object returned by the lookup to the specific interface for your Web service. This is shown on Listing 3, where the HelloService extends the generic JAX-RPC Service interface.

Listing 3. Alternative JNDI lookupContext ic= new InitialContext();HelloServiceInterface service = (HelloServiceInterface) ic.lookup("java:comp/env/service/HelloService");

The Service Interface obtained is then used to get a static stub, dynamic proxy, or a DII Call object, as described in the "Service access" section below.

Service access

In previous sections, you saw that a JAX-RPC ServiceFactory acts as a factory for JAX-RPC Services. Similarly, a JAX-RPC Service acts as a factory for proxies and stubs.

Page 19: Web Services in Action - Himalay Majumdar

Once you have instantiated a Service, there are three methods for accessing and invoking the Web service:

1. Stub2. Dynamic Proxy3. Dynamic Invocation Interface (DII).

Stub and dynamic proxy methods use the Service Endpoint Interface (SEI). It is basically the Java representation of the Web service operations described in the WSDL port type element. It is a Java interface defining methods used by the Java client to interact with the Web service. The SEI is generated by a WSDL to Java mapping tool (such as Apache Axis' Java2WSDL or IBM WSDK's WSDL2Client).

Stub

The stub method uses a platform-specific stub created before runtime during the WSDL to Java mapping stage. Because the stub is created before runtime, it is sometimes called a static stub. It is a Java class implementing the SEI. A WSDL to Java mapping tool generates the client-side artifacts needed; basically, the tool imports the WSDL service definition and creates the corresponding Java code. The artifacts include an SEI, a Stub, and optionally holders, serializers, deserializers, and utility classes. JAX-RPC recommends an instance of a stub to be bound to a specific protocol and transport, such as a SOAP binding stub. For the stub method, the steps to perform are:

1. Get a JAX-RPC Service.2. Obtain a stub.3. Invoke the Web service's operations on the stub.

Steps 2 and 3 are shown in Listing 4. Note that it is also possible to use the JAX-RPC Service's getPort method (described in the next section) to obtain a stub.

Listing 4. Accessing a Web service through a stubHello myStub = (Hello) service.getHello();System.out.println(myStub.getGreeting("Jane");

The advantage of this method is its simplicity. Basically, only two lines of code are required to access and invoke a Web service's operation. However, you need to know the WSDL URL at development-time and run your WSDL to Java mapping tool. Also, these stubs are not portable because they depend on implementation classes and should not be

SEI

A Service Endpoint Interface (SEI) is the Java representation of a WSDL port type.

Page 20: Web Services in Action - Himalay Majumdar

packaged as part of an application. The design of portable stubs is out-of-scope for JAX-RPC 1.0 and 1.1.

Dynamic proxy

From a JAX-RPC Service, you can use a proxy to invoke the Web service's operations. The proxy is a Java class implementing the SEI. A proxy is obtained with the JAX-RPC Service's getPort() method, which takes the name of the port for the Web service you want to invoke (found in the WSDL document), as well as the SEI implemented by the proxy. It is called dynamic because the proxy is created at runtime. The steps for dynamic proxy clients are:

1. Get a JAX-RPC Service.2. Obtain a proxy using the JAX-RPC Service's getPort() method in order to invoke

the Web service's operations.

In step 1, for unmanaged clients, a JAX-RPC Service is obtained from the JAX-RPC ServiceFactory by passing the WSDL URL as well as the Web service name parameter to the createService() method. For J2EE container-managed clients, you get a JAX-RPC Service from JNDI lookup. Listing 5 shows the dynamic proxy method (step 2) to invoke the "getGreeting" operation on the Web service.

Listing 5. Invoking a Web Service's operation on a dynamic proxyString namespace = "http://Hello.com";String portName = "Hello";QName portQN = new QName(namespace, portName); Hello myProxy = service.getPort(portQN, Hello.class);System.out.println(myProxy.getGreeting("Jane"));

This is all the code you need to write to invoke a Web service using the dynamic proxy method. The advantage of using this method is that you write portable, vendor-independent code. However, you need to know the WSDL URL at development-time and you need to run your WSDL to Java mapping tool against the WSDL document before runtime. If you do not have this information, or if the WSDL URL is likely to change, you should use the DII method instead.

Dynamic Invocation Interface (DII)

The JAX-RPC Call interface supports the dynamic invocation of a Web services' operations. With this method, you do not need to know the WSDL URL at development-time. Instead of obtaining a proxy from the JAX-RPC Service, the JAX-RPC Service acts as a factory for instantiating JAX-RPC Calls. The steps for this method are:

1. Get a JAX-RPC Service.

Page 21: Web Services in Action - Himalay Majumdar

2. Instantiate a JAX-RPC Call using JAX-RPC Service's createCall() method.3. Configure your Call instance with its setter methods.4. Invoke the Web service's operation using the JAX-RPC Call's invoke method.

In step 1, for unmanaged clients, a JAX-RPC Service is obtained from the JAX-RPC ServiceFactory by passing only the name of the Web service (not the WSDL URL) to the createService() method. For J2EE container-managed clients, you get a JAX-RPC Service from JNDI lookup. In step 3, configuration parameters are: name of the operation, port type, address of the target service endpoint, return type. Refer to section 8.2.4.2 of the JAX-RPC specification for the standard set of properties (see Resources). Steps 2 to 4 are shown in Listing 6.

Listing 6. Invoking a Web service using the DII methodString namespace = "http://Hello.com";String portName = "Hello";QName portQN = new QName(namespace, portName);String operationName = "getGreeting";

Call call = service.createCall();call.setPortTypeName(portQN);call.setOperationName(new QName(namespace, operationName));call.setProperty(Call.ENCODINGSTYLE_URI_PROPERTY, ""); call.addParameter("param1", <xsd:string>,ParameterMode.IN);call.setReturnType(<xsd:string>);Object[] inParams = new Object[] {"Jane"};String ret = (String) call.invoke(inParams);

You can reuse the Call instance to invoke other operations on the Web service.

Note: What was just described is not the only way to invoke them. For example, it is possible to invoke createCall() with port type name and operation name parameters.

Making DII calls through a Call object is programmatically more complex than using a stub or dynamic proxy. However, the advantage of using a DII Call interface is that a client can call a remote procedure without development-time knowledge of the WSDL URI or the Web service operations' signatures. This makes the code easy to modify if the Web service details change. With DII clients, runtime classes generated by WSDL to Java mapping tools (emitters) are not required like the dynamic proxy or static stub cases. However, if you know the Web service you want to invoke is unlikely to change, you should use dynamic proxy because configuring the Call instance can be complex.

Page 22: Web Services in Action - Himalay Majumdar

Dynamic Discovery and Invocation (DDI)

Dynamic Discovery and Invocation (DDI) is the ultimate use of Web services' flexibility where a Web service client can dynamically discover and invoke a Web service without any prior knowledge of it. Although DII clients, described in the previous section, do not require development-time knowledge of a Web service's details, they do not involve the process of discovering the Web service. A DDI client performs three steps:

1. Discovers the Web service's details from UDDI: finds the business providing the service and then the URL of the WSDL document describing the service

2. Reads the WSDL document to find information on the Web service: namespace, service, ports, and parameters

3. Invokes the service.

In step 1, the UDDI Registry Enquiry API is used to browse the UDDI registry. In step 2, the UDDI4J API is used to parse the WSDL document. Finally, in step 3, the DII method (described in the previous section) is used.

Page 23: Web Services in Action - Himalay Majumdar

Exposing Model Data via Web Services

Servlet Endpoint EJB Endpoint

Create and expose a Session Facade for the application. Using a Session Facade to expose an application's operations will make it easier to migrate to enterprise bean endpoints at a later date.

Create reusable enterprise bean components that expose an XML interface in the form of a generic XML schema. This allows the enterprise bean component to be reused in the context of a Web service. For document-centric Web services, a document can flow to the EJB tier and enterprise bean components can manipulate the document. Object-centric Web services deserialize documents at the service endpoint.

The biggest new feature of J2EE 1.4 is the ability of J2EE components to act both as web service providers and consumers. “J2EE applications can expose a web service from the EJB tier using a stateless session bean or from the web tier using a plain Java object.” Additionally, both server-side components and J2EE client applications have a standard way of declaring references to external web services.

http://docs.jboss.org/jbossas/jboss4guide/r2/html/ch12.html

Page 24: Web Services in Action - Himalay Majumdar

SOAP Handlers

JAX-RPC requires SOAP over HTTP for interoperability. JAX-RPC provides support for SOAP message processing model through the SOAP message handler functionality. This enables developers to build SOAP specific extensions to support security, logging and any other facility based on the SOAP messaging. JAX-RPC uses SAAJ API for SOAP message handlers. SAAJ provides a standard Java API for constructing and manipulating SOAP messages with attachments.

JAX-RPC provides support for document-based messaging. Using JAX-RPC, any MIME-encoded content can be carried as part of a SOAP message with attachments. This enables exchange of XML documents, images and other MIME types across Web services.

JAX-RPC supports HTTP level session management and SSL based security mechanisms. This enables you to develop secure Web services. More advanced SOAP message-level security will be addressed in the evolution of JAX-RPC technology.

Steps for Implementing a Service:

1. Define Web Service Endpoint Interface 2. Implement Web Service class and methods

3. Package and deploy

JAX-RPC handlers allow you to intercept a SOAP message at various times during a service invocation. Handlers are similar to servlet filters. Handlers can exist on both the client and the server side. If you use JAX-RPC on the client side, you can have a handler process a SOAP request message right before it goes on the network, and you can process the response message before it is returned to the client. Similarly, you can intercept an incoming SOAP request message on the server before invoking the service implementation, as well as the outgoing response.

Several handlers can be combined into what is called a "handler chain". Each handler processes the SOAP message, which is then passed on to the next handler in the chain. The exact sequence in which this happens is configurable.

To develop a JAX-RPC handler, you simply create a class that implements the javax.xml.rpc.handler.Handler interface. It has three methods to handle SOAP requests, responses and faults, respectively.

Handlers are defined in the JAX-RPC specification. However, the "Enterprise Web Services" (JSR109) specification describes how they are used in a J2EE environment and adds some clarification to the way handlers are managed by the application server. We will assume that your Web service runs on a J2EE application server and hence we will follow the definitions of JSR109 as well as JAX-RPC.

Page 25: Web Services in Action - Himalay Majumdar

Handlers are shared across multiple service invocations. In other words, they can store information that is only valid for a particular client or server instance. You can compare this to the way servlets are handled. When a new instance of a handler is created, its init(...) method is called. That allows you to set up things that you can use for multiple invocations. Before the handler is removed, the destroy() method is called, so that you can do cleanup in there. As a rule of thumb, however, you should avoid storing any state in a handler altogether.

Handlers can be configured either programmatically or, in case you are running a J2EE application server, they are configured in the Web service deployment descriptor. Handlers and handler chains are defined on a per service basis. They can be defined in both the server and client side deployment descriptors. Listing below shows the deployment descriptor for our sample service, showing how a handler class called handler.PerformanceHandler is registered for the HelloWorldService service (webservices.xml):

Now let's look at how you can create a handler that measures the response time of your service implementation. We will assume that you have created a HelloWorld web service, which simply returns a String message. Listing below shows the code for the service implementation bean:

public class HelloWorld {public String helloWorld(String message) {

return "Hello " + message;}

}

The handler will be configured for the server that hosts the Web service. It will be invoked on both the request and the response message, so that we can measure the elapsed time.

Each handler must implement the javax.xml.rpc.handler.Handler interface. Or, you can make your life a bit easier by simply inheriting the javax.xml.rpc.handler.GenericHandler class, which provides default implementations for all the methods. For storing performance results, we use a class called Logger, which we set up in the init() method. Moreover, the application server passes a javax.xml.rpc.handler.HandlerInfo object into this method, which we need to cache as well:

Page 26: Web Services in Action - Himalay Majumdar

public class PerformanceHandler extends GenericHandler {

protected HandlerInfo info = null;protected Logger logger = null;

public void init(HandlerInfo arg) {info = arg;logger =

Logger.getLogger("c://temp//HelloWorldServiceLog");}

public void destroy() {try {

logger.close();} catch (Exception x) {}

}

...}

Note that we close the Logger object when the handler instance is destroyed.

Each handler implements the handleRequest method, which is invoked when a request message arrives:

public boolean handleRequest(MessageContext context) {try {

Date startTime = new Date();context.setProperty("startTime", startTime);

} catch (Exception x) {x.printStackTrace();

}return true;

}

Here you can see that we store the current time in the message context as a property called "startTime". The application server will guarantee that the same message context object is passed into the handleResponse method, so that we can measure the elapsed time there:

public boolean handleResponse(MessageContext context) {try {

Date startTime = (Date)context.getProperty("startTime");Date endTime = new Date();long elapsedTime = endTime.getTime() -

startTime.getTime();logger.write("Elapsed time is " + elapsedTime+"\n");

} catch (Exception x) {x.printStackTrace();

}return true;

}

Page 27: Web Services in Action - Himalay Majumdar

JAX-RPC defines a mechanism with which you can manage service invocations by intercepting request and response messages without having to change the actual service consumer or provider. In J2EE, you can configure handlers in a deployment descriptor, without writing any code, providing you with a powerful way of controlling SOAP messages as they pass through your system.

Handlers let you access/modify SOAP request and response messages, but typically used to process service contexts in SOAP header blocks.

Possible example handlers: encryption, decryption, authentication, authorization, logging, auditing, caching.

Handlers are pluggable and chainable through standardized programming API, portable across implementations. Handler has its own lifecycle: JAX-RPC runtime system calls init(...), destroy() of a handler. Handler instances can be pooled (stateless). MessageContext is used to share properties among handlers in a handler chain.

On the service client side: a request handler is invoked before an RPC request is communicated to the target service endpoint, a response or fault handler is invoked before an RPC response is returned to the client.

On a service endpoint: a request handler is invoked before an RPC request is dispatched to the target service endpoint, a response or fault handler is invoked before communication back to the service client from the target service endpoint.

javax.xml.rpc.handler.Handler interface is required to be implemented by a SOAP message handler:

***********************************************************************THE BASIC HANDLER INTERFACE AND THE GENERIC HANDLER ABSTRACT CLASS***********************************************************************package javax.xml.rpc.handler;

import javax.xml.namespace.QName;

public interface Handler {

public boolean handleRequest(MessageContext context); // 'false' will block the HandlerChain public boolean handleResponse(MessageContext context); // 'false' will block the HandlerChain public boolean handleFault(MessageContext context); // 'false' will block the HandlerChain public abstract void init(HandlerInfo config); public abstract void destroy(); public QName[] getHeaders(); }

Page 28: Web Services in Action - Himalay Majumdar

package javax.xml.rpc.handler;

import javax.xml.namespace.QName;

public abstract class GenericHandler implements Handler {

protected GenericHandler() {}

public boolean handleRequest(MessageContext context) { return true; }

public boolean handleResponse(MessageContext context) { return true; }

public boolean handleFault(MessageContext context) { return true; }

public void init(HandlerInfo config) {} public void destroy() {} public abstract QName[] getHeaders();}

***********************************************************************

Example of generic SOAP message handler:

package com.example;

public class SampleSOAPHeaderHandler implements javax.xml.rpc.handler.Handler {

public SampleSOAPHeaderHandler() { ... }

public boolean handleRequest(MessageContext context) {try {

SOAPMessageContext smc = (SOAPMessageContext)context;

SOAPMessage msg = smc.getMessage();SOAPPart sp = msg.getSOAPPart();SOAPEnvelope se = sp.getEnvelope();SOAPHeader sh = se.getHeader();

// Process one or more header blocks// ...// Next step based on the processing model for

this handler

} catch(Exception ex) {// throw exception

}}

Page 29: Web Services in Action - Himalay Majumdar

}

Alternative: Sample handler which extends GenericHandler:

package com.example;

public class SampleSOAPHeaderHandler extends GenericHandler {

public boolean handleRequest(MessageContext ctx) {try {

SOAPMessageContext mc = (SOAPMessageContext)ctx;SOAPMessage msg = mc.getMessage();SOAPPart sp = msg.getSOAPPart();SOAPEnvelop se = sp.getEnvelope();SOAPHeader header= se.getHeader();

// now we can process the header

if (everything is fine) {return true; // with 'true' handler chain

continues processing} else {

return false; // return 'false' results in chaining to stop

}} catch(Exception ex) {}

}}

SAAJ API

--Alternate API for XML processing

http://www.ibm.com/developerworks/xml/library/x-jaxmsoap/

Page 30: Web Services in Action - Himalay Majumdar

XML Parsers

The Extensible Markup Language (XML) and Java technology are natural partners in helping developers exchange data and programs across the Internet. That's because XML has emerged as the standard for exchanging data across disparate systems, and Java technology provides a platform for building portable applications.

This partnership is particularly important for Web services, which promise users and application developers program functionality on demand from anywhere to anywhere on the Web. XML and Java technology are recognized as ideal building blocks for developing Web services and applications that access Web services.

But how do you couple these partners in practice? More specifically, how do you access and use an XML document (that is, a file containing XML-tagged data) through the Java programming language? One way to do this, perhaps the most typical way, is through parsers that conform to the Simple API for XML (SAX) or the Document Object Model (DOM). Both of these parsers are provided by Java API for XML Processing (JAXP). Java developers can invoke a SAX or DOM parser in an application through the JAXP API to parse an XML document -- that is, scan the document and logically break it up into discrete pieces. The parsed content is then made available to the application.

SAX

The SAX API

The Simple API for XML (SAX) defines an API for an event-based parser. Being event-based means that the parser reads an XML document from beginning to end, and each time it recognizes a syntax construction, it notifies the application that is running it. The SAX parser notifies the application by calling methods from the ContentHandler interface. For example, when the parser comes to a less than symbol ("<"), it calls the startElement method; when it comes to character data, it calls the characters method; when it comes to the less than symbol followed by a slash ("</"), it calls the endElement method, and so on. To illustrate, let's look at part of the example XML document from the first section and walk through what the parser does for each line. (For simplicity, calls to the method ignorableWhiteSpace are not included.)

<priceList>   [parser calls startElement]  <coffee>    [parser calls startElement]    <name>Mocha Java</name>    [parser calls startElement,                characters, and endElement]    <price>11.95</price>    [parser calls startElement,                characters, and endElement]  </coffee>    [parser calls endElement]

Page 31: Web Services in Action - Himalay Majumdar

The default implementations of the methods that the parser calls do nothing, so you need to write a subclass implementing the appropriate methods to get the functionality you want. For example, suppose you want to get the price per pound for Mocha Java. You would write a class extending DefaultHandler (the default implementation of ContentHandler) in which you write your own implementations of the methods startElement and characters.

You first need to create a SAXParser object from a SAXParserFactory object.

SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser saxParser = factory.newSAXParser();saxParser.parse("priceList.xml", handler);

The result of calling the method parse depends, of course, on how the methods in handler were implemented. The SAX parser will go through the file priceList.xml line by line, calling the appropriate methods. In addition to the methods already mentioned, the parser will call other methods such as startDocument, endDocument, ignorableWhiteSpace, and processingInstructions, but these methods still have their default implementations and thus do nothing.

The following method definitions show one way to implement the methods characters and startElement so that they find the price for Mocha Java and print it out. Because of the way the SAX parser works, these two methods work together to look for the name element, the characters "Mocha Java", and the price element immediately following

public void startElement(..., String elementName, ...){  if(elementName.equals("name")){    inName = true;  } else if(elementName.equals("price") && inMochaJava ){    inPrice = true;    inName = false;  }} public void characters(char [] buf, int offset, int len) {  String s = new String(buf, offset, len);  if (inName && s.equals("Mocha Java")) {    inMochaJava = true;    inName = false;  } else if (inPrice) {    System.out.println("The price of Mocha Java is: " + s);    inMochaJava = false;    inPrice = false;    }  }}

Page 32: Web Services in Action - Himalay Majumdar

Once the parser has come to the Mocha Java coffee element, here is the relevant state after the following method calls:

next invocation of startElement -- inName is true

next invocation of characters -- inMochaJava is true

next invocation of startElement -- inPrice is true

next invocation of characters -- prints price

The SAX parser can perform validation while it is parsing XML data, which means that it checks that the data follows the rules specified in the XML document's schema. A SAX parser will be validating if it is created by a SAXParserFactory object that has had validation turned on. This is done for the SAXParserFactory object factory in the following line of code.

factory.setValidating(true);

When it comes to fast, efficient reading of XML data, SAX is hard to beat . It requires little memory, because it does not construct an internal representation (tree structure) of the XML data. Instead, it simply sends data to the application as it is read—your application can then do whatever it wants to do with the data it sees.

In effect, the SAX API acts like a serial I/O stream. You see the data as it streams in, but you can’t go back to an earlier position or leap ahead to a different position. In general, it works well when you simply want to read data and have the application act on it.

The DOM API

The Document Object Model (DOM), defined by the W3C DOM Working Group, is a set of interfaces for building an object representation, in the form of a tree, of a parsed XML document. Once you build the DOM, you can manipulate it with DOM methods such as insert and remove, just as you would manipulate any other tree data structure. Thus, unlike a SAX parser, a DOM parser allows random access to particular pieces of data in an XML document. Another difference is that with a SAX parser, you can only read an XML document, but with a DOM parser, you can build an object representation of the document and manipulate it in memory, adding a new element or deleting an existing one.

In the previous example, we used a SAX parser to look for just one piece of data in a document. Using a DOM parser would have required having the whole document object model in memory, which is generally less efficient for searches involving just a few

Page 33: Web Services in Action - Himalay Majumdar

items, especially if the document is large. In the next example, we add a new coffee to the price list using a DOM parser. We cannot use a SAX parser for modifying the price list because it only reads data.

Let's suppose that you want to add Kona coffee to the price list. You would read the XML price list file into a DOM and then insert the new coffee element, with its name and price. The following code fragment creates a DocumentBuilderFactory object, which is then used to create the DocumentBuilder object builder. The code then calls the parse method on builder, passing it the file priceList.xml.

DocumentBuilderFactory factory =          DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse("priceList.xml");

At this point, document is a DOM representation of the price list sitting in memory.

//We're at the Mocha Java node. Create and insert the new element.

  Node newCoffeeNode = document.createElement("coffee");

  Node newNameNode = document.createElement("name");  Text tnNode = document.createTextNode("Kona");  newNameNode.appendChild(tnNode);

  Node newPriceNode = document.createElement("price");  Text tpNode = document.createTextNode("13.50");  newPriceNode.appendChild(tpNode);

http://java.sun.com/j2ee/1.3/docs/tutorial/doc/IntroWS4.html

Page 34: Web Services in Action - Himalay Majumdar

JAXB

JAXB allows Java developers to access and process XML data without having to know XML or XML processing. For example, there's no need to create or use a SAX parser or write callback methods.

Using JAXB, you would:

← Bind the schema for the XML document. ← Unmarshal the document into Java content objects. The Java content objects

represent the content and organization of the XML document, and are directly available to your program.

After unmarshalling, your program can access and display the data in the XML document simply by accessing the data in the Java content objects and then displaying it. There is no need to create and use a parser and no need to write a content handler with callback methods. What this means is that developers can access and process XML data without having to know XML or XML processing.

Bind the Schema

Page 35: Web Services in Action - Himalay Majumdar

JAXB simplifies access to an XML document from a Java program by presenting the XML document to the program in a Java format. The first step in this process is to bind the schema for the XML document into a set of Java classes that represents the schema.

Schema: A schema is an XML specification that governs the allowable components of an XML document and the relationships between the components. For example, a schema identifies the elements that can appear in an XML document, in what order they must appear, what attributes they can have, and which elements are subordinate (that is, are child elements) to other elements. An XML document does not have to have a schema, but if it does, it must conform to that schema to be a valid XML document. JAXB requires that the XML document you want to access has a schema, and that schema is written in the W3C XML Schema Language (see the box "Why W3C XML Schema Language?").

.

Why W3C XML Schema Language?

The W3C XML Schema Language is not the only schema language. In fact, the XML specification describes document-type definitions (DTDs) as the way to express a schema. In addition, pre-release versions of the JAXB Reference Implementation worked only with DTDs -- that is, not with schemas written in the XML Schema Language. However, the XML Schema Language is much richer than DTDs. For example, schemas written in the XML Schema Language can describe structural relationships and data types that can't be expressed (or can't easily be expressed) in DTDs. There are tools available to convert DTDs to the W3C XML Schema Language, so if you have DTD-based schemas that you used with an earlier version of the JAXB Reference Implementation, you can use these tools to convert the schemas to XML Schema Language.

Binding: Binding a schema means generating a set of Java classes that represents the schema. All JAXB implementations provide a tool called a binding compiler to bind a schema (the way the binding compiler is invoked can be implementation-specific).

xjc.sh -p test.jaxb books.xsd -d work

The -p option identifies a package for the generated classes, and the -d option identifies a target directory. So for this command, the classes are packaged in test.jaxb within the work directory.

Page 36: Web Services in Action - Himalay Majumdar

Unmarshal the Document

Unmarshalling an XML document means creating a tree of content objects that represents the content and organization of the document. The content tree is not a DOM-based tree. In fact, content trees produced through JAXB can be more efficient in terms of memory use than DOM-based trees.

To unmarshal an XML document, you:

Create a JAXBContext object. This object provides the entry point to the JAXB API. When you create the object, you need to specify a context path. This is a list of one or more package names that contain interfaces generated by the binding compiler. By allowing multiple package names in the context path, JAXB allows you to unmarshal a combination of XML data elements that correspond to different schemas.

For example, the following code snippet creates a JAXBContext object whose context path is test.jaxb, the package that contains the interfaces generated for the books.xsd schema: ←← import javax.xml.bind.JAXBContext;←← JAXBContext jc = JAXBContext.newInstance("test.jaxb");

←← Create an Unmarshaller object. This object controls the process of

unmarshalling. In particular, it contains methods that perform the actual unmarshalling operation. For example, the following code snippet creates an Unmarshaller object:

←← import javax.xml.bind.Unmarshaller;←← Unmarshaller unmarshaller = jc.createUnmarshaller();

←← Call the unmarshal method. This method does the actual unmarshalling of the

XML document. For example, the following statement unmarshals the XML data in the books.xml file:

←←

Page 37: Web Services in Action - Himalay Majumdar

← Collection collection= (Collection)← unmarshaller.unmarshal(new File( "books.xml"));←

Note that a Collection here is a test.jaxb.Collection, not a java.util.Collection.

← Use the get methods in the schema-derived classes to access the XML data. Recall that the classes that a JAXB compiler generates for a schema include get and set methods you can use to respectively obtain and specify data for each type of element and attribute in the schema. For example, the following statement gets the data in the books and book elements:

←← CollectionType.BooksType booksType = collection.getBooks();← List bookList = booksType.getBook();

After obtaining the data, you can display it directly from your program. Here, for example, is a program that unmarshals the data in the books.xml file and then displays the data. If you run the program, you should see the following result: Book details Item id: 999Book Name: Learning JAXBBook ISBN: 123445Book Price: 34 $Book category: otherBook promotion: 10% on this book if purchased by March 2003No of Authors 1Author Name Jane Doe

Book details Item id: 129Book Name: Java Webservices today and BeyondBook ISBN: 522965Book Price: 29 $Book category: magazineBook promotion: Buy one get Learning webservices Part 1 freeNo of Authors 2Author Name John BrownAuthor Name Peter T.

Validating the Source Data: Notice that the program includes the following statement:

unmarshaller.setValidating(true);

This statement highlights an important feature of JAXB: you can have it validate the source data against the associated schema as part of the unmarshalling operation. In this case, the statement asks JAXB to validate the source data against its schema. If the data is found to be invalid (that is, it doesn't conform to the schema) the JAXB implementation can report it and might take further action. JAXB providers have a lot of flexibility here. The JAXB specification mandates that all provider

You can validate source data against an associated schema as part of the unmarshalling operation.

Page 38: Web Services in Action - Himalay Majumdar

implementations report validation errors when the errors are encountered, but the implementation does not have to stop processing the data