Use XMLBeans to create a Web service client

Use XMLBean technology to write a Web service client that requires a Custom Data Type as the input to a method. With XMLBeans you don't need to generate static stubs on the client side. We discuss this benefit in detail.

Shailesh K. Mishra (shailekm@in.ibm.com), Software Engineer, IBM

Shailesh K. Mishra is software engineer at the IBM Software Lab in Gurgaon, India. He is currently working on the "BizPortlets" project and his main area of interest is business integration.



18 July 2006

Also available in Chinese Japanese

Introduction

Apache XMLBeans is an open source, XML and Java-binding tool based on the StAX specification. XMLBeans can be used to generate Java classes and interfaces from an XML Schema. The generated Java classes may be used to parse or generate XML documents that conform to the schema, and fortunately, XMLBeans provide intuitive ways to handle the XML to make it easier for you to access and manipulate XML data and documents in Java.

Let's break it down and take a look at some of the characteristics of the XMLBeans approach to XML.

  • XMLBeans provide a familiar Java object-based view of XML data while retaining access to the original, native XML structure.
  • The XML's integrity as a document is retained with XMLBeans. XML-oriented APIs commonly take the XML apart in order to bind to its parts. With XMLBeans, the entire XML instance document is handled as a whole. The XML data is stored in memory as XML. This means that the document order is preserved as well as the original element content with whitespace.
  • With types generated from schema, access to XML instances is through JavaBean-like accessors, with get and set methods.
  • XMLBeans is designed with XML schema in mind from the beginning -- XMLBeans supports all XML schema definitions.
  • Access to XML is fast.

The XML schema is the starting point for XMLBean development. The XML Schema specification (See the Resources section) provides a rich data model that enables you to express sophisticated structure and constraints on your data. For example, an XML schema can enforce control over how data is ordered in a document, or constraints on particular values. For example, an entry date that must be later than 2000. In Java, custom code is typically required to enforce such rules. XMLBeans honors schema constraints.

We can use XMLBeans technology to generate Java classes and interfaces for Types Definitions in the WSDL file. To do so, run the WSDLTypes_To_JAVATypes class (See the Download section). You need to change the WSDL URL in main method of this class. This step is very important as it generates the Java classes and interfaces which are used to prepare the SOAP message to invoke the web service. The Generating Java classes and interfaces for Types Definitions in WSDL section talks in detail about WSDLTypes_To_JAVATypes class.


Configure your workspace to work with XMLBeans

The first step we need to take is to download the binary distribution of XMLBeans, which can be found at The XML page at apache.org. Then, extract the archive into a directory. Add the .jar files contained in the XMLBeans distribution to your project.


Generating Java classes and interfaces for Types Definitions in WSDL

The XMLBeans framework provides what you need to compile a WSDL file into Java objects. With this facility, we can generate Java classes and interfaces associated with the data types that are defined in the WSDL and can be used by the Web service clients. This ability to interpret a WSDL document dynamically offers a greater degree of power over standard static XML-parsing and processing techniques.

The code listing below shows a WSDLTypes_To_JAVATypes class file, adapted from the article Using Java to Handle Custom WSDLData Types, which you will find in the Resources section. You will see how to generate schemas from data types defined in the WSDL file.

Listing 1. generateSchemas method
generateSchemas(String schemadir, String classesdir,
 String javasrcdir, String wsdlFileName) {
   boolean doNotValidateContents = false;
   XmlObject wsdlDoc = null;
   MyEntityResolver myentityResolver = new MyEntityResolver();
   ArrayList outerrlistener = new ArrayList();
   XmlErrorWatcher errlistener = new XmlErrorWatcher(outerrlistener);
   ArrayList schemalist = new ArrayList();
   try {
	SchemaTypeLoader loader =
	 XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader());
				.................................	
				................................
	addWsdlSchemas(wsdlFileName,
	 (DefinitionsDocument)wsdlDoc,errlistener,doNotValidateContents,schemalist);
				.................................

Method addWsdlSchemas generates the schemas, validate them and add them into a arraylist.

Listing 2. addWsdlSchemas method
addWsdlSchemas(String wsdlFileName,DefinitionsDocument definitionsDocument,
    XmlErrorWatcher  errlistener, boolean doNotValidateContents,ArrayList schemalist){
                         
      XmlObject[]types = definitionsDocument.getDefinitions().getTypesArray();
for (int j = 0; j < types.length; j++) {
	XmlObject[] schemas = types[j].selectPath("declare namespace"
        + " xs=\"http://www.w3.org/2001/XMLSchema\""        
		+ " xs:schema");
			if (schemas.length == 0) {
	StscState.addWarning(errlistener, "The WSDL " + wsdlFileName
		+ " has no schema documents in namespace "
		+ "'http://www.w3.org/2001/XMLSchema'",
	  XmlErrorCodes.GENERIC_ERROR,definitionsDocument);
	continue;
	}
for (int k = 0; k < schemas.length; k++) {
if (schemas[k] instanceof SchemaDocument.Schema) {
SchemaDocumentImpl.SchemaImpl schemaImpl = (SchemaDocumentImpl.SchemaImpl) schemas[k];
System.out.println ("Validating schema...");
if (schemaImpl.validate(opts)) {
	System.out.println("Schema passed validation");
	schemalist.add(schemas[k]);
	}else {
	 System.out.println("Schema failed validation");
	 schemalist.add(schemas[k]);
	}
}

The methods compileSchema and generateJavaSource will compile the generated schemas and generate the Java files respectively. Finally the CompileJavaSource method compiles the Java source files.

Listing 3. compileSchemas,generateJavaSource,CompileJavaSource method
SchemaTypeSystem compileSchemas(String schemadir,ArrayList schemalist, MyEntityResolver 
    myentityResolver,XmlErrorWatcher errlistener) 
{
    SchemaDocument.Schema[] sdocs = (SchemaDocument.Schema[]) schemalist
       .toArray(new SchemaDocument.Schema[schemalist.size()]);
    ResourceLoader cpResourceLoader = null;
    SchemaTypeLoader linkTo = SchemaTypeLoaderImpl.build (null, cpResourceLoader, null);.
	.................
	.................
	SchemaTypeSystem sts = SchemaTypeSystemCompiler.compile (params);
	....................


generateJavaSource(String classesdir,String javasrcdir, SchemaTypeSystem sts) {
	File classesDir = new File(classesdir);
	File srcDir = IOUtil.createDir(new File("."), javasrcdir);
		
	// now, generate the source files
	XmlOptions options = new XmlOptions();
	boolean verbose = false;
	boolean incrSrcGen = false;
	Repackager repackager = null;
	FilerImpl filer = new FilerImpl(classesDir, srcDir, repackager,
		verbose, incrSrcGen);

	System.out.println ("Generating Java source...");
	if (SchemaTypeSystemCompiler.generateTypes(sts, filer, options)) {
	............................
	...............................

CompileJavaSource(List sourceFiles, String classesDirName) {
	File classesDir = new File(classesDirName);
	boolean debug = false;
	System.out.println ("Compiling Java source files...");
	If (CodeGenUtil.externalCompile (sourceFiles, classesDir, null, debug)) {	
	..................
	..................

Writing a client for your Web service

To write a Web service client using XMLBeans, we will prepare a SOAP message directly and send this SOAP message to a Web service URL.

Prepare the SOAP message

  • Step 1. Create a SOAPMessaage instance by calling

    SOAPMessage smsg =MessageFactory.newInstance ().createMessage ()
  • Step 2. Create a SOAP Envelope and Body

    SOAPPart prt = smsg.getSOAPPart ();
    SOAPEnvelope env = prt.getEnvelope ();
    SOAPBody bdy = env.getBody ();

  • Step 3. Instantiate the class for the method's input type

    GetPlacedOrderDocument Placedorderdoc=GetPlacedOrderDocument.Factory.newInstance ();
    GetPlacedOrderDocument.GetPlacedOrder order=placedorderdoc.addNewGetPlacedOrder ();
    Customer customer=order.addNewCust ();
    customer.setId (835163);
    customer.setFname ("Jerry");
    customer.setLname ("tukker");
    customer.setLocation ("abcd..");

  • Step 4. Add the above class instance to the body of the SOAP message

    Node nd= placedorderdoc.getDomNode ();
    SOAPBodyElement ele = bdy.addDocument ((Document) nd);

  • Step 5. Send the SOAP message to the Web Service end point

    URL endpoint = new URL ("http://localhost:9080/Sample/services/SampleWebService");
    SOAPMessage response = con.call (smsg, endpoint);

The code listing below shows the code after the steps above have been performed:

Listing 4. SOAP Client

Click to see code listing

Listing 4. SOAP Client

MessageFactory mfact = MessageFactory.newInstance();
			SOAPMessage smsg = mfact.createMessage();

			SOAPPart prt = smsg.getSOAPPart();
			SOAPEnvelope env = prt.getEnvelope();
			SOAPBody bdy = env.getBody();

GetPlacedOrderDocument placedorderdoc=GetPlacedOrderDocument.Factory.newInstance();
			GetPlacedOrderDocument.GetPlacedOrder order=placedorderdoc.addNewGetPlacedOrder();
			Customer customer=order.addNewCust();
			customer.setId(835163);
			customer.setFname("Jerry");
			customer.setLname("tukker");
			customer.setLocation ("abcd...");
			smsg.writeTo(System.out);
			System.out.println();
			Node nd = placedorderdoc.getDomNode();
			SOAPBodyElement ele = bdy.addDocument((Document) nd); 
.............................
URL endpoint = new URL("http://localhost:9080/Sample/services/SampleWebService");
			
                                           //Send the message
			SOAPMessage response = con.call(smsg, endpoint);
			response.writeTo(System.out);
...........................

In the above code listing GetPlacedOrderDocument is an interface generated from the WSDL file (from the sample Web service used for testing the code) after running the WSDLTypes_To_JAVATypes class. This Web service has a method getPlacedOrder, which takes Customer class as argument. The Customer class have four attributes id, fname, lname and location.


Conclusion

This tutorial helped you write a Web service client using XMLBeans. We generated schemas from a WSDL file, compiled them and finally generated Java source from the compiled schemas. Once we are ready with the Java source, we can easily prepare SOAP message and send it to the Web service url. This allows you the freedom from having to manually author SOAP messages, and from having to do the serialization and deserialization of custom Java objects.

The author would like to thank Krishnakumar Balachandar (KK), WebSphere Community Edition/Geronimo L3 Support Lead, for his review and comments on this article.


Download

DescriptionNameSize
Sample codexmlbeansample.zip96KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=147231
ArticleTitle=Use XMLBeans to create a Web service client
publish-date=07182006