Sunteți pe pagina 1din 29

Chapter 16

Building Web Services with JAX-WS

JAX-WS stands for Java API for XML Web Services. JAX-WS is a technology for
building web services and clients that communicate using XML. JAX-WS allows
developers to write message-oriented as well as RPC-oriented web services.

In JAX-WS, a web service operation invocation is represented by an XML-based


protocol such as SOAP. The SOAP specification defines the envelope structure, encoding
rules, and conventions for representing web service invocations and responses. These
calls and responses are transmitted as SOAP messages (XML files) over HTTP.

Although SOAP messages are complex, the JAX-WS API hides this complexity from the
application developer. On the server side, the developer specifies the web service
operations by defining methods in an interface written in the Java programming
language. The developer also codes one or more classes that implement those methods.
Client programs are also easy to code. A client creates a proxy (a local object representing
the service) and then simply invokes methods on the proxy. With JAX-WS, the developer
does not generate or parse SOAP messages. It is the JAX-WS runtime system that
converts the API calls and responses to and from SOAP messages.

With JAX-WS, clients and web services have a big advantage: the platform independence
of the Java programming language. In addition, JAX-WS is not restrictive: a JAX-WS
client can access a web service that is not running on the Java platform, and vice versa.
This flexibility is possible because JAX-WS uses technologies defined by the World
Wide Web Consortium (W3C): HTTP, SOAP, and the Web Service Description Language
(WSDL). WSDL specifies an XML format for describing a service as a set of endpoints
operating on messages.
Creating a Simple Web Service and Client with JAX-WS

This section shows how to build and deploy a simple web service and client. The source
code for the service is in tut-
install/javaeetutorial5/examples/jaxws/helloservice/ and the client is in tut-
install/javaeetutorial5/examples/jaxws/simpleclient/.

Figure 16-1 illustrates how JAX-WS technology manages communication between a web
service and client.

Figure 16-1 Communication between a JAX-WS Web Service and a Client

The starting point for developing a JAX-WS web service is a Java class annotated with
the javax.jws.WebService annotation. The @WebService annotation defines the class
as a web service endpoint.

A service endpoint interface or service endpoint implementation (SEI) is a Java


interface or class, respectively, that declares the methods that a client can invoke on the
service. An interface is not required when building a JAX-WS endpoint. The web service
implementation class implicitly defines an SEI.

You may specify an explicit interface by adding the endpointInterface element to the
@WebService annotation in the implementation class. You must then provide an interface
that defines the public methods made available in the endpoint implementation class.

These are the basic steps for creating the web service and client:

1. Code the implementation class.


2. Compile the implementation class.

3. Use wsgen to generate the artifacts required to deploy the service.


4. Package the files into a WAR file.

5. Deploy the WAR file. The web service artifacts (which are used to communicate
with clients) are generated by the Application Server during deployment.

6. Code the client class.

7. Use wsimport to generate and compile the web service artifacts needed to
connect to the service.

8. Compile the client class.

9. Run the client.

The sections that follow cover these steps in greater detail.

Requirements of a JAX-WS Endpoint

JAX-WS endpoints must follow these requirements:

The implementing class must be annotated


with either the
javax.jws.WebService or javax.jws.WebServiceProvider annotation.
The implementing class may explicitly reference an SEI through the
endpointInterface element of the @WebService annotation, but is not required to
do so. If no endpointInterface is specified in @WebService, an SEI is implicitly
defined for the implementing class.

The business methods of the implementing class must be public, and must not be
declared static or final.

Business methods that are exposed to web service clients must be annotate with
javax.jws.WebMethod.

Business methods that are exposed to web service clients must have JAXB-
compatible parameters and return types.

The implementing class must not be declared final and must not be abstract.

The implementing class must have a default public constructor.

The implementing class must not define the finalize method.

The implementing class may use the javax.annotation.PostConstruct or


javax.annotation.PreDestroy annotations on its methods for life cycle event
callbacks.
The @PostConstruct method is called by the container before the implementing
class begins responding to web service clients.

The @PreDestroy method is called by the container before the endpoint is removed
from operation.

Coding the Service Endpoint Implementation Class

In this example, the implementation class, Hello, is annotated as a web service endpoint
using the @WebService annotation. Hello declares a single method named sayHello,
annotated with the @WebMethod annotation. @WebMethod exposes the annotated method to
web service clients. sayHello returns a greeting to the client, using the name passed to
sayHello to compose the greeting. The implementation class also must define a default,
public, no-argument constructor.

package helloservice.endpoint;

import javax.jws.WebService;

@WebService
public class Hello {
private String message = new String("Hello, ");

public void Hello() {}

@WebMethod
public String sayHello(String name) {
return message + name + ".";
}
}

Building, Packaging, and Deploying the Service

You can build, package, and deploy the helloservice application using either NetBeans
IDE or ant.

Building, Packaging, and Deploying the Service Using NetBeans IDE

Follow these instructions to build, package, and deploy the helloservice example to
your Application Server instance using the NetBeans IDE IDE.

1. In NetBeans IDE, select FileOpen Project.


2. In the Open Project dialog, navigate to tut-
install/javaeetutorial5/examples/jaxws/.

3. Select the helloservice folder.

4. Select the Open as Main Project check box.


5. Click Open Project.

6. In the Projects tab, right-click the helloservice project and select Undeploy and
Deploy.

This builds and packages to application into helloservice.war, located in tut-


install/javaeetutorial5/examples/jaxws/helloservice/dist/, and deploys this
WAR file to your Application Server instance.

Testing the Service without a Client

The Application Server Admin Console allows you to test the methods of a web service
endpoint. To test the sayHello method of HelloService, do the following:

1. Open the Admin Console by typing the following URL in a web browser:

http://localhost:4848/

2. Enter the admin user name and password to log in to the Admin Console.
3. Click Web Services in the left pane of the Admin Console.

4. Click Hello.

5. Click Test.

6. Under Methods, enter a name as the parameter to the sayHello method.

7. Click the sayHello button.

This will take you to the sayHello Method invocation page.

8. Under Method returned, youll see the response from the endpoint.

A Simple JAX-WS Client

HelloClient is a stand-alone Java program that accesses the sayHello method of


HelloService. It makes this call through a port, a local object that acts as a proxy for the
remote service. The port is created at development time by the wsimport tool, which
generates JAX-WS portable artifacts based on a WSDL file.

Coding the Client

When invoking the remote methods on the port, the client performs these steps:
1. Uses the javax.xml.ws.WebServiceRef annotation to declare a reference to a
web service. @WebServiceRef uses the wsdlLocation element to specify the URI of
the deployed services WSDL file.
2. @WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/he
llo?wsdl")
static HelloService service;

3. Retrieves a proxy to the service, also known as a port, by invoking getHelloPort


on the service.

Hello port = service.getHelloPort();

The port implements the SEI defined by the service.

4. Invokes the ports sayHello method, passing to the service a name.

String response = port.sayHello(name);

Here is the full source of HelloClient, which is located in the tut-


install/javaeetutorial5/examples/jaxws/simpleclient/src/java/directory.

package simpleclient;

import javax.xml.ws.WebServiceRef;
import helloservice.endpoint.HelloService;
import helloservice.endpoint.Hello;

public class HelloClient {


@WebServiceRef(wsdlLocation="http://localhost:8080/
helloservice/hello?wsdl")
static HelloService service;

public static void main(String[] args) {


try {
HelloClient client = new HelloClient();
client.doTest(args);
} catch(Exception e) {
e.printStackTrace();
}
}

public void doTest(String[] args) {


try {
System.out.println("Retrieving the port from
the following service: " + service);
Hello port = service.getHelloPort();
System.out.println("Invoking the sayHello operation
on the port.");

String name;
if (args.length > 0) {
name = args[0];
} else {
name = "No Name";
}

String response = port.sayHello(name);


System.out.println(response);
} catch(Exception e) {
e.printStackTrace();
}
}
}

Building and Running the Client

You can build and run the simpleclient application using either NetBeans IDE orant.
To build the client, you must first have deployed helloservice, as described inBuilding,
Packaging, and Deploying the Service.

Building and Running the Client in NetBeans IDE

Do the following to build and run simpleclient:

1. In NetBeans IDE, select FileOpen Project.


2. In the Open Project dialog, navigate to tut-
install/javaeetutorial5/examples/jaxws/.

3. Select the simpleclient folder.

4. Select the Open as Main Project check box.

5. Click Open Project.

6. In the Projects tab, right-click the simpleclient project and select Run.

You will see the output of the application client in the Output pane.

Types Supported by JAX-WS

JAX-WS delegates the mapping of Java programming language types to and from XML
definitions to JAXB. Application developers dont need to know the details of these
mappings, but they should be aware that not every class in the Java language can be used
as a method parameter or return type in JAX-WS. For information on which types are
supported by JAXB, see Chapter 17, Binding between XML Schema and Java Classes.

Web Services Interoperability and JAX-WS


JAX-WS 2.0 supports the Web Services Interoperability (WS-I) Basic Profile Version 1.1.
The WS-I Basic Profile is a document that clarifies the SOAP 1.1 and WSDL 1.1
specifications to promote SOAP interoperability. For links related to WS-I, see Further
Information about JAX-WS.

To support WS-I Basic Profile Version 1.1, the JAX-WS runtime supports doc/literal and
rpc/literal encodings for services, static ports, dynamic proxies, and DII.

Java Architecture for XML Binding (JAXB)

By Ed Ort and Bhakti Mehta, March 2003

You will find the following topics covered in this article:

What's JAXB?
An Example: Accessing an XML Document

o Bind the Schema


o Unmarshal the Document
Another Example: Building an XML Document

o Bind the Schema


o Create the Content Tree
o Marshal the Content Tree
A Final Example: Updating an XML Document
Binding Can Be Customized
Distinct Advantages
Run the Examples

XML and Java technology are recognized as ideal


building blocks for developing Web services and
applications that access Web services. A new Java
What's JAXB?
API called Java Architecture for XML Binding (JAXB)
can make it easier to access XML documents from
applications written in the Java programming
language.

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. In the SAX approach, the parser starts at the beginning of the
document and passes each piece of the document to the application in the sequence it finds it.
Nothing is saved in memory. The application can take action on the data as it gets it from the
parser, but it can't do any in-memory manipulation of the data. For example, it can't update the
data in memory and return the updated data to the XML file.

In the DOM approach, the parser creates a tree of objects that represents the content and
organization of data in the document. In this case, the tree exists in memory. The application can
then navigate through the tree to access the data it needs, and if appropriate, manipulate it.

Now developers have another Java API at their disposal that can make it easier to access XML
documents: Java Architecture for XML Binding (JAXB). A Reference Implementation of the API is
now available in the Java Web Services Developer Pack V 1.1.

Let's look at JAXB in action, and compare it to SAX and DOM-based processing.

An Example: Accessing an XML Document


Suppose you need to develop a Java application that accesses and displays data in XML
documents such as books.xml. These documents contain data about books, such as book name,
author, description, and ISBN identification number. You could use the SAX or DOM approach to
access an XML document and then display the data. For example, suppose you took the SAX
approach. In that case, you would need to:

Write a program that creates a SAX parser and then uses that parser to parse the XML
document. The SAX parser starts at the beginning of the document. When it encounters
something significant (in SAX terms, an "event") such as the start of an XML tag, or the text inside
of a tag, it makes that data available to the calling application.

Create a content handler that defines the methods to be notified by the parser when it
encounters an event. These methods, known as callback methods, take the appropriate action on
the data they receive.

As an example, here is a program that uses JAXP to create and use a SAX parser to parse an
XML document. The program uses a
content handler, JAXB allows Java developers to access and process
MyContentHandler, to display the XML data without having to know XML or XML
data passed to it by the SAX parser. processing. For example, there's no need to create or
use a SAX parser or write callback methods.
Now let's look at how you use JAXB to access an XML document such as books.xml and
display its data. 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

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?").

Assume, for this example, that the books.xml document has a schema, books.xsd, that is written
in the W3C XML Schema Language. This schema defines a <Collection> as an element that has
a complex type. This means that it has child elements, in this case, <book> elements. Each
<book> element also has a complex type named bookType. The <book> element has child
elements such as <name>, <ISBN>, and <author>. Some of these have their own child
elements.

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). For example, the JAXB Reference
Implementation provides a binding compiler that you can invoke through scripts. Suppose, for
example, you want to bind the books.xsd schema using the binding compiler provided by the
JAXB Reference Implementation. Suppose too that you're working in the Solaris Operating
Environment. Here's a command you can use to run the script that binds the schema:

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.

In response, the binding compiler generates a set of interfaces and a set of classes that
implement the interfaces. Here are the interfaces it generates for the books.xsd schema:

CollectionType.java . Represents the unnamed complex type for the


<Collection> element.

Collection.java. Represents the <Collection> element.


BookType.java. Represents the BookType complex type.
ObjectFactory.java. Contains methods for generating instances of the interfaces.

Here are the classes that implement the interfaces (these are generated in an impl
subdirectory). Note that these classes are implementation-specific -- in this example, they are
specific to the Reference Implementation. Because the classes are implementation-specific,
classes generated by the binding compiler in one JAXB implementation will probably not work
with another JAXB implementation. So if you change to another JAXB implementation, you
should rebind the schema with the binding compiler provided by that implementation.

impl/CollectionTypeImpl.java . Implements the CollectionType interface


described in CollectionType.java.

impl/CollectionImpl.java . Implements the Collection interface described in


Collection.java.
impl/BookTypeImpl.java . Implements the BookType interface described in
BookType.java.

In total, the generated classes represent the entire books.xsd schema. Notice that the classes
define get and setmethods that are used to respectively obtain and specify data for each type of
element and attribute in the schema.

You then compile the generated interfaces and classes. For example:

javac test/jaxb/*.java test/jaxb/impl/*.java

This compiles all of the interfaces and classes in the test.jaxb package generated by the
binding compiler.

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.

The content objects are instances of the classes produced by the binding compiler. In addition to
providing a binding compiler, a JAXB implementation must provide runtime APIs for JAXB-related
operations such as marshalling. The APIs are provided as part of a binding framework. The
binding framework comprises three packages. The primary package, javax.xml.bind,
contains classes and interfaces for performing operations such as unmarshalling, marshalling,
and validation (marshalling and validation will be covered later). A second package,
javax.xml.bind.util, contains a number of utility classes. The third package,
javax.xml.bind.helper, is designed for JAXB implementation providers.

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:
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: 999
Book Name: Learning JAXB
Book ISBN: 123445
Book Price: 34 $
Book category: other
Book promotion: 10% on this book if purchased by March 2003
No of Authors 1
Author Name Jane Doe

Book details
Item id: 129
Book Name: Java Webservices today and Beyond
Book ISBN: 522965
Book Price: 29 $
Book category: magazine
Book promotion: Buy one get Learning webservices Part 1 free
No of Authors 2
Author Name John Brown
Author 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 You can validate source data against an associated
it and might take further action. JAXB schema as part of the unmarshalling operation.
providers have a lot of flexibility here.
The JAXB specification mandates
that all provider implementations report validation errors when the errors are encountered, but the
implementation does not have to stop processing the data. Some provider implementations might
stop processing when the first error is found, others might stop even if many errors are found. In
other words, it is possible for a JAXB implementation to successfully unmarshal an invalid XML
document, and build a Java content tree. However, the result won't be valid. The main
requirement is that all JAXB implementations must be able to unmarshal valid documents.

You also have the flexibility of turning the validation switch off if you don't want to incur the
additional validation processing overhead.

Unmarshalling Other Sources: Although the example described in this section shows how to
unmarshal XML data in a file, you can unmarshal XML data from other input sources such as an
InputStreamobject, a URL, or a DOM node. You can even unmarshal transformed XML
data. For example, you can unmarshal a javax.xml.transform.sax.SAXSource object. You
can also unmarshal SAX events -- in other words, you can do a SAX parse of a document and
then pass the events to JAXB for unmarshalling.

An Alternative: Accessing Data without Unmarshalling: JAXB also allows you to access XML
data without having to unmarshal it. One of the classes generated from a schema,
ObjectFactory, contains methods to generate objects for each of the schema-derived
interfaces and classes. For example, the package generated for the books.xsd schema
includes an ObjectFactory class that has methods such as createCollection to create a
Collection object, and createBookType to create a BookType object. You can use these
methods to create a tree of content objects without doing any unmarshalling. All your program
needs is access to the ObjectFactory class that's in the package for the pertinent schema.
Then you can use the appropriate methods in the ObjectFactory class to create the objects
you need. After you create the objects, you need to provide their content. To do that, you use the
set methods in the objects.

Another Example: Building an XML Document


Instead of accessing data in an XML document, suppose you need to build an XML document
through a Java application. Here too using JAXB is easier. Let's investigate.

You could use the DOM approach to build an XML document, but not SAX. That's because you
would need to build and populate the content of the document in memory -- recall that SAX does
not allow you to perform any in-memory manipulation of data. Using the DOM approach, your
program needs to create and use DOM objects and methods to build the document. DOM is
designed to represent the content and organization of data in a document as a tree of objects. To
build the document, your program uses DOM to create a Document object that represents the
document. Your program then uses Document object methods to create other objects that
represent the nodes of the tree. Each node contains content for the XML document. You then
append the nodes in an order that reflects the organization of the tree. In other words, your
program uses DOM object methods to create a root node, and append the root node to the
Document object. Then it creates child nodes and appends them to the root node. If a child node
has children of its own, your program uses DOM object methods to create those nodes and
append them to their parent node.

Unlike the SAX approach, there is no need in DOM to write a content handler and callback
methods. However the DOM approach requires you to understand the organization of the
document tree. In fact, if you use DOM to access data, you create a parser that builds a tree, and
then you use DOM methods to navigate to the appropriate object in the tree that contains the
data you need. So an understanding of the tree's organization is a requirement. Compare this to
JAXB, where you have direct access to unmarshalled XML data through objects in the content
tree. As in DOM-based processing, JAXB allows access to data in non-sequential order, but it
doesn't force an application to navigate through a tree to access the data. In addition, with all the
creating and appending of objects that represent the nodes of the tree, the DOM approach can be
tedious.

Here, for example, is a program that uses DOM to build and populate a document, and then write
the document to an XML file. Notice that the type of data that gets populated into the document is
similar to the data in the books.xml file that was used in the first example, Accessing an XML
Document. In fact, the program validates the document it builds against the books.xsd schema
that was used in the first example.
As in DOM-based processing, JAXB allows access to
data in non-sequential order, but it doesn't force an
Now let's look at how you use JAXB
application to navigate through a tree to access the
to build the same document, validate
data.
it against the books.xsd schema, and write the document to an XML file. Using JAXB, you
would:

Bind the schema for the XML document (if it isn't already bound).

Create the content tree.

Marshal the content tree into the XML document.

In this process, you don't deal with the intricacies of the DOM object model or even need to know
XML.

Bind the Schema


This is the same operation you perform prior to unmarshalling a document. In this case, the
schema is for the XML document you want to build. Of course, if you've already bound the
schema (for instance, you unmarshalled an XML document, updated the data, and now want to
write the updated data back to the XML document), you don't have to bind the schema again.

Create the Content Tree


The content tree represents the content that you want to build into the XML document. You can
create the content tree by unmarshalling XML data, or you can create it using the
ObjectFactory class that's generated by binding the appropriate schema. Let's use the
ObjectFactory approach. First, create an instance of the ObjectFactory class:

ObjectFactory objFactory = new ObjectFactory();

Next, use create methods in the ObjectFactory object to create each of the objects in the
content tree. For example:

Collection collection=
(Collection) objFactory.createCollection();
Collection.BooksType booksType = objFactory.
createCollectionTypeBooksType();
BookType book = objFactory.createBookType();

Then use set methods in the created objects to specify data values. For example:

book.setItemId("307");
book.setName("JAXB today and beyond");
Marshal the Content Tree

Marshalling is the opposite of unmarshalling. It creates an XML document from a content tree. To
marshal a content tree, you:

Create a JAXBContext object, and specify the appropriate context path -- that is, the
package that contains the classes and interfaces for the bound schema. As is the case for
unmarshalling, you can specify multiple package names in the context path. That gives you a way
of building an XML document using a combination of XML data elements that correspond to
different schemas.

import javax.xml.bind.JAXBContext;

JAXBContext jaxbContext = JAXBContext.newInstance("test.jaxb");


Create a Marshaller object. This object controls the process of marshalling. In
particular, it contains methods that perform the actual marshalling operation.
import javax.xml.bind.Marshaller;

Marshaller marshaller = jaxbContext.createMarshaller();

The Marshaller object has properties that you can set through the setProperty method. For
example, you can specify the output encoding to be used when marshalling the XML data. Or you
can tell the Marshaller to format the resulting XML data with line breaks and indentation. The
following statement turns this output format property on -- line breaks and indentation will appear
in the output format:
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
new Boolean(true));

Call the marshal method. This method does the actual marshalling of the content tree.
When you call the method, you specify an object that contains the root of the content tree, and
the output target. For example, the following statement marshals the content tree whose root is in
the collection object and writes it as an output stream to the XML file jaxbOutput.xml:

marshaller.marshal(collection,
new FileOutputStream("jaxbOutput.xml"));
Here, for example, is a program that creates a content tree, fills it with data, and then marshals
the content tree to an XML file.
Validating the Content Tree: Notice that validation is not performed as part of the marshalling
operation. In other words, unlike the case for unmarshalling, there is no setValidating method
for marshalling. Instead, when marshalling data, you use the Validator class that is a part of
the binding framework to validate a content tree against a schema. For example:

import javax.xml.bind.Validator;

Validator validator = jaxbContext.createValidator();


validator.validate(collection));

Validating the data as a separate operation from marshalling gives you a lot of flexibility. For
example, you can do the validating at one point in time, and do the marshalling at another time.
Or you can do some additional processing in between the two operations. Note that the JAXB
specification doesn't require a content tree to be valid before it's marshalled. That doesn't
necessarily mean that a JAXB implementation will allow invalid data to be marshalled -- it might
marshal part or all of the invalid data, or not. But all JAXB implementations must be able to
marshal valid data.

Marshalling to Other Targets: Although the example described in this section shows how to
marshal data to an XML file, you can marshal to other output formats such as an OutputStream
object or a DOM node. You can also marshal to a transformed data format such as
javax.xml.transform.SAXResult. You can even marshal to a content handler. This allows
you to process the data as SAX events.

A Final Example: Updating an XML Document


Here's a final example, one that logically combines elements of accessing an XML document and
building an XML document. Suppose you need to update an XML document. In the DOM
approach, you would create and use a DOM parser to navigate to the appropriate object in the
tree that contains the data you need, update the data, and then write the updated data to an XML
file. Here, for example, is a program that uses DOM to update an XML document. As discussed in
Building an XML Document, the DOM approach is relatively tedious and forces you to know the
organization of the content tree.

Here, by comparison, is a JAXB program that updates an XML document. Specifically, it updates
an unmarshalled content tree and then marshals it back to an XML document. Notice how JAXB
simplifies the process. The program has direct access to the object it needs to update. The
program uses a get method to access the data it needs, and a set method to update the data.

Although it's tempting to think that the XML data can make a "roundtrip" unchanged, there's no
guarantee of that. In other words, if you use JAXB to unmarshal an XML document and then
marshal it back to the same XML file, there's no guarantee that the XML document will look
exactly the same at it did originally. For example, the indentation of the resulting XML document
might be a bit different than the original. The JAXB specification does not require the preservation
of the XML information set in a roundtrip from XML document-to-Java representation-to XML
document. But it also doesn't forbid the preserving of it.

Binding Can Be Customized


The JAXB specification describes the default behavior for binding a subset of XML schema
components to Java components. The specification identifies which XML schema components
must be bound and to what Java representations these components are bound. For example, the
XML built-in datatype xsd:string must be bound to the Java data type java.lang.String.
All JAXB compiler implementations must implement the default binding specifications. However
there are times when the default behavior might not be what you want. For example, suppose you
want an XML data type mapped to a Java data type that is different than the type called for by the
default binding specification. Or you want the binding compiler to assign a name of your choice to
a class that it generates.

To meet these and other customization needs, JAXB allows you to annotate a schema with
binding declarations that override or extend the default binding behavior. JAXB allows these
declarations to be made "inline" -- that is, in the schema, or in a separate document.

Let's look at a customization example. Here is an annotated version of the books.xsd schema
that was used in the previous examples. The annotations in this example are inline.

Notice the annotation element near the top of the schema:

<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings generateIsSetMethod="true">

bindingStyle="modelGroupBinding"
choiceContentProperty="true" >

<xjc:serializable uid="12343"/>
<jaxb:javaType name="short"
xmlType="xs:long"
printMethod="javax.xml.bind.DatatypeConverter.printShort"
parseMethod="javax.xml.bind.DatatypeConverter.parseShort"/
>

</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>

All binding declarations are in an annotation element and its subordinate appinfo element. In
fact, all inline binding declarations must be made this way.

This block of code demonstrates a number of customizations that you can make to a schema:

Make global customizations: The <jaxb:globalBindings...> element specifies binding


declarations that have global scope. In JAXB, binding declarations can be specified at different
levels, or "scopes." Each scope inherits from the scopes above it, and binding declarations in a
scope override binding declarations in scopes above it. Global scope is at the top of the scope
hierarchy. It covers all the schema elements in the source schema and (recursively) any schemas
that are included or imported by the source schema. Global scope is followed in the hierarchy by
Schema scope (covers all the schema elements in the target namespace of a schema), Definition
scope (covers all schema elements that reference a specified type definition or a global
declaration), and Component scope (applies only to a specific schema element that was
annotated with a binding declaration).

Notice that the namespace prefix ( jaxb) for the <globalBindings> element is bound to
http://java.sun.com/xml/ns/jaxb. This URI contains the core schema for binding declarations.

Add method signatures. The declaration generateIsSetMethod="true" tells the binding


compiler to generate isSet methods for the properties of all generated classes. These methods
are used to determine if a property in a class is set or has a default value.

Change binding style. By default, schema components that have complex types and that have a
content type property of mixed or element-only are bound with a style called element binding. In
element binding, each element in the complex type is mapped to a unique content property.
Alternatively, you can change the binding style to model group binding by specifying
bindingStyle="modelGroupBinding" choiceContentProperty="true" . In model group binding,
schema components that have complex type and that are nested in the schema are mapped
to Java interfaces. This gives users a way to specifically customize these nested
components. For example, the following component is nested in the customized schema:

<xs:element name="promotion">

<xs:complexType>
<xs:choice>
<xs:element name="Discount" type="xs:string" />
<xs:element name="None" type="xs:string"/>

</xs:choice>
</xs:complexType>
</xs:element>

As result of the global declarations made earlier, the binding compiler will generate the following
methods for the elements tagged as choice:

java.lang.Object getDiscountOrNone();
void setDiscountOrNone(java.lang.Object value);
boolean is SetDiscountOrNone();

Include vendor-specific extensions. The declaration <xjc:serializableuid="12343"/>


is an extension binding declaration. The xjc prefix binds to a namespace for extension binding
declarations. These declarations are vendor-specific extensions to the binding declarations
defined in http://java.sun.com/xml/ns/jaxb. Here, the vendor-specific declaration covers the
binding of classes that implement java.io.Serializable. The serial version uid 12343 will
be assigned to each generated class.

Customize the binding of a simple data type. The declaration <jaxb:javaType


name="short"xmlType="xs:long" binds the XML datatype xs:long to the Java data type
short. This overrides the default binding behavior, which is to bind xs:long to the Java
primitive data type long. The additional declaration
printMethod="javax.xml.bind.DatatypeConverter.parseShort" tells the binding
compiler to use the DatatypeConverter.parseShort method in JAXB's javax.xml.bind
package to convert a lexical representation of the XML data type into the Java data type. The
parse method is invoked by the JAXB provider's implementation during unmarshalling. The
additional declaration
printMethod="javax.xml.bind.DatatypeConverter.printShort" tells the binding
compiler to use the DatatypeConverter.printShort method in JAXB's javax.xml.bin
package to convert the Java data type into a lexical representation of the XML data type. The
print method is invoked by the JAXB provider's implementation during marshalling.

Additional customizations: Other annotations in the schema illustrate additional types of


customization, such as annotating a specific schema element to a Java Content Interface or Java
Element Interface. This is done through a <class> binding declaration. In the annotated schema
example, a <class> binding declaration is used to specify the name MyCollection for the
interface bound to the <Collection> class. Another binding declaration in the annotated
schema example binds the <bookCategory> element to its Java representation as a typesafe
enumeration class. Although not illustrated in the annotated schema, another type of
customization you can make is to specify javadoc for a generated package or class. These are
only some of the many binding customizations that JAXB allows.

You can see the impact of the binding declarations by binding the annotated schema. When you
do the binding, specify the extension option, as in the following command:

xjc.sh -extension -p cust books_customization.xsd


The extension option allows you to use vendor-provided extensions. You need this to enable
the extension binding declaration in the schema. If you don't specify the extension option, the
binding compiler will run in "strict" mode. In this mode, it allows only for default bindings, and will
produce an error message when it comes to the extension binding declaration.

After you run the program, examine the interfaces and classes that the binding compiler
generates, and compare them to the interfaces and classes generated from the uncustomized
schema. For example, here is the CollectionType.java file generated for the unnamed
complex type for the <Collection> element. Notice the additional methods that have been
added because of the binding customizations.

Distinct Advantages
Let's reiterate a number of important advantages of using JAXB:

JAXB simplifies access to an XML document from a Java program:

.
o JAXB allows you to access and process XML data without having to know XML
or XML processing. Unlike SAX-based processing, there's no need to create a SAX parser or
write callback methods.
o JAXB allows you to access data in non-sequential order, but unlike DOM-based
processing, it doesn't force you to navigate through a tree to access the data.
o By unmarshalling XML data through JAXB, Java content objects that represent
the content and organization of the data are directly available to your program.
JAXB uses memory efficiently: The tree of content objects produced through JAXB tends
can be more efficient in terms of memory use than DOM-based trees.
JAXB is flexible:
o You can unmarshal XML data from a variety of input sources, including a file, an
InputStream object, a URL, a DOM node, or a transformed source object.
o You can marshal a content tree to a variety of output targets, including an XML
file, an OutputStream object, a DOM node, or a transformed data object
o You can unmarshal SAX events -- for example, you can do a SAX parse of a
document and then pass the events to JAXB for unmarshalling.
o JAXB allows you to access XML data without having to unmarshal it. Once a
schema is bound you can use the ObjectFactory methods to create the objects and then use
set methods in the generated objects to create content.
o You can validate source data against an associated schema as part of the
unmarshalling operation, but you can turn validation off if you don't want to incur the additional
validation overhead.
o You can validate a content tree, using the Validator class, separately from
marshalling. For example, you can do the validating at one point in time, and do the marshalling
at another time.
JAXB's binding behavior can be customized in a variety of ways.
Java API for XML Registries
The Java API for XML Registries (JAXR) provides a uniform and standard Java API for accessing
various kinds of XML registries.

Overview of JAXR
This section provides a brief overview of JAXR. It covers the following topics:

What Is a Registry?
What Is JAXR?
JAXR Architecture

What Is a Registry?

An XML registry is an infrastructure that enables the building, deployment, and discovery of web
services. It is a neutral third party that facilitates dynamic and loosely coupled business-to-
business (B2B) interactions. A registry is available to organizations as a shared resource, often in
the form of a web-based service.

Currently there are a variety of specifications for XML registries. These include

The ebXML Registry and Repository standard, which is sponsored by the Organization for the
Advancement of Structured Information Standards (OASIS) and the United Nations Centre for the
Facilitation of Procedures and Practices in Administration, Commerce and Transport
(U.N./CEFACT)
The Universal Description, Discovery, and Integration (UDDI) project, which is being developed by
a vendor consortium

A registry provider is an implementation of a business registry that conforms to a specification for


XML registries.

What Is JAXR?

JAXR enables Java software programmers to use a single, easy-to-use abstraction API to access
a variety of XML registries. A unified JAXR information model describes content and metadata
within XML registries.

JAXR gives developers the ability to write registry client programs that are portable across
various target registries. JAXR also enables value-added capabilities beyond those of the
underlying registries.

The current version of the JAXR specification includes detailed bindings between the JAXR
information model and both the ebXML Registry and the UDDI version 2 specifications. You can
find the latest version of the specification at
http://java.sun.com/xml/downloads/jaxr.html

At this release of the J2EE platform, JAXR implements the level 0 capability profile defined by the
JAXR specification. This level allows access to both UDDI and ebXML registries at a basic level.
At this release, JAXR supports access only to UDDI version 2 registries.

Currently several public UDDI version 2 registries exist.

Service Registry, an ebXML registry and repositry with a JAXR provider, is available as part of the
Sun Java Enterprise System.

JAXR Architecture

The high-level architecture of JAXR consists of the following parts:

A JAXR client: This is a client program that uses the JAXR API to access a business registry via a
JAXR provider.
A JAXR provider: This is an implementation of the JAXR API that provides access to a specific
registry provider or to a class of registry providers that are based on a common specification.

A JAXR provider implements two main packages:

javax.xml.registry, which consists of the API interfaces and classes that define the registry
access interface.
javax.xml.registry.infomodel, which consists of interfaces that define the information
model for JAXR. These interfaces define the types of objects that reside in a registry and how they
relate to each other. The basic interface in this package is the RegistryObject interface. Its
subinterfaces include Organization, Service, and ServiceBinding.

The most basic interfaces in the javax.xml.registry package are

Connection. The Connection interface represents a client session with a registry provider.
The client must create a connection with the JAXR provider in order to use a registry.
RegistryService. The client obtains a RegistryService object from its connection. The
RegistryService object in turn enables the client to obtain the interfaces it uses to access the
registry.

The primary interfaces, also part of the javax.xml.registrypackage, are

BusinessQueryManager, which allows the client to search a registry for information in


accordance with the javax.xml.registry.infomodel interfaces. An optional interface,
DeclarativeQueryManager, allows the client to use SQL syntax for queries. (The
implementation of JAXR in the Application Server does not implement
DeclarativeQueryManager.)
BusinessLifeCycleManager, which allows the client to modify the information in a registry
by either saving it (updating it) or deleting it.

When an error occurs, JAXR API methods throw a JAXRException or one of its subclasses.

Many methods in the JAXR API use a Collection object as an argument or a returned value.
Using a Collection object allows operations on several registry objects at a time.
Figure 10-1 illustrates the architecture of JAXR. In the Application Server, a JAXR client uses the
capability level 0 interfaces of the JAXR API to access the JAXR provider. The JAXR provider in
turn accesses a registry. The Application Server supplies a JAXR provider for UDDI registries.

Figure 10-1 JAXR Architecture

JAXR, Mini Tutorial


What is JAXR?

JAXR provides a uniform and standard Java API for accessing XML registries. It
is included in Sun's Web Services Developer Pack version 1.0. JAXR removes the
dependence between applications and nonstandard toolkits by giving developers a
rich, simple, and standard extension API to communicate with registry providers
using these very same open standards.

JAXR Concept

A naming service allows a name to be associated with an object and the object to
be located by that name. A similiar concept like a DNS service. It holds a
mapping between a domain name and an IP address. For example, you can send a
query for www.javacamp.org and a DNS server will return the IP address
208.170.149.158.

A registry is a special form of a naming service. It not only allows a lookup, but
also allows objects to be registered. The remote method invocation (RMI) registry
and the Java Naming and Directory Interface(JNDI) API are two examples of Java
registry and lookup services. When you develop a remote object and register it in
the registry by associating it with a name. Other applications may use the JNDI
API or RMI naming service to query that registry for the name and get a remote
reference (or a stub) back for the remote object.

A registry in the context of Web services essentially provides this same


functionality. Registries give applciations and business a place to store
information about their Web services and give clients the ability to query and
retrieve details about such business. Every registry has an information model and
a set of registry services.

Universal Description, Discovery, and Integration(UDDI) and the Electronic


Business Extensible Markup Language(ebXML) are two dominant industry
standands for Web services. Java developers need a standard API to access these
heterogeneous registries from Java. This is how JAXR comes in.

Core JAXR

The JAXR architecture is based on the concept of pluggable providers. JAXR


provides a layer of abstraction to developers. Developers write applications using
a standand JAXR client API and a standard JAXR information model to interact
with business registries of UDDI and ebXML.

JAXR has two capability levels:

o level 0: support for UDDI registry


o level 1: support for an ebXML and UDDI registry

All JAXR providers are required to support level 0. Support for level 1 is
optional.

The JAXR's information mode is contained in the javax.xml.registry.infomodel


package, and at its core is a javax.xml.registry.infomodel.RegistryObject. All
objects in the registry implement the RegistryObject, and essentially everything in
the registry is a RegistryObject.

UDDI specifications require that a UDDI provider expose the registry though a
Web-based HTML interface. Developers can use eithre this interface or the JAXR
API.
How to publish to a UDDI Registry

In order to show it clearly, we explain the steps with a piece of code. You may
need to download Java XML(JAX) pack from http://java.sun.com/xml

Before publish to UDDI, you may need to do the following steps:

o Set the properties for the ConnectionFactory


o Create a connection
o Authenticate the UDDI userName and password with the registry
o Obtain a reference to
1. RegistryService
2. BusinessLifeCycleManager
3. BusinessQueryManager

Then, there are five steps involved:

o Create an Organization object


o Create a User object with a Telephone-Number and EmailAddress and set
is as the primary contact for the Organization.
o Create a Web Service for the Organization
o Create ServiceBindings for the Service
o Classify the Organization

How to Query a UDDI Registry

A registry can be queried for different fields: Organization, Concepts,


ServiceBindings, Service, Associations, and so on. by using the relevant methods
from the BusinessQuery Manager interface.

There are five steps involved:

o Use the reference to the BusinessQueryManager and one of the methods


below to query the registry.

BulkResponse findOrganizations(findQualifiers, namePatterns,


classifications, specifications, externalIdentifiers, externalLinks);
BulkResponse findServiceBindings(serviceKey, findQualifiers,
classifications, specifications);
BulkResponse findeServices(orgKey, findQualifiers, namePatterns,
classifications, specifications);
o Create a namePattern to query on
o Parse the BulkResponse object returned freom the find method and obtain
the collection of Organization objects.
o Query each organization object to obtain details about the primary contact
and the services registered.
o Close the connection to the registry.

S-ar putea să vă placă și