![]() |
Windows / Web Services with Axis and XMLBeans Example
< Web Services using Tomcat, Axis, and XMLBeans | Working With Windows | Getting rid of Nero Scout > Web Services Example
|
Page Contents |
The Contract |
The Service |
The Client |
Deployment Configuration |
Build, Deploy and Test |
This is an adjunct to the Web Services using Tomcat, Axis, and XMLBeans page.
For this example, I will demonstrate a simplistic method for creating a web service for a bookstore. Given a list of books and a zip code for the shipping destination, the service should return a price for each book and the shipping charges. Our service will be called createInvoice
. If this were a more in-depth example, we would probably look up the books in a database to determine availability and weight, and then figure shipping charges based on the book’s weight and our shipper’s rate charts; but this is just a proof of concept and we will simply generate random numbers in our Business Logic.
All the files I wrote that are needed for this project are included in bookstore-example.zip. Simply download that file and extract it somewhere using 7-Zip (or your favorite ZIP program). You may need to edit the init
target of the Ant build file build.xml
(in the top example
directory) to adjust for your configuration.
That ZIP file provides the files for use directly in the Windows environment. If you will be using Cygwin and have it configured for Unix line terminators, then download bookstore-example-nl.zip instead.
Both ZIP files provide the following files:
example/
|-- build.xml |-- contract/ | |-- basket.xsd | `-- invoice.xsd |-- data/ | `-- test_basket.xml |-- deployment/ | |-- deploy.wsdd | `-- undeploy.wsdd `-- src/ `-- com/ `-- mybookstore/ |-- client/ | `-- BookstoreClient.java |-- service/ | `-- BookstoreService.java `-- test/ `-- BookstoreServiceTest.java
I use Cygwin and emacs as my development environment. If you prefer using the Command Window and Notepad (or some other Windows editors or IDEs for Java and XML), remember to use %ENVIRONMENT_VARIABLE%
instead of $ENVIRONMENT_VARIABLE
and to switch your slashes around backward.
For more information about Tomcat, Axis, and XMLBeans, including the procedure for installing them all correctly under Windows, see the Web Services using Tomcat, Axis, and XMLBeans page. For more information about Ant (a Java-based build tool) including installation instructions, see the apache.org Ant project website.
This is a high-level contract, not the SOA service contract --- we let Axis handle that.
We want to send the createInvoice
service enough information about the books desired to uniquely specify them --- actually, we will overspecify, otherwise we could just pass an integer (the ISBN) and miss out on all the XMLBeans fun. We want to be able to buy more than one book at a time, to hopefully save on S&H. In order to figure out the shipping costs, we need the destination zip code.
What we want back are (at least) the retail price for each book and a total S&H charge. We will ignore sales tax until Congress passes more laws to screw up the Internet commerce. It would be helpful to have a subtotal and a grand total provided as well, because our client program would like to be lazy.
We could use class instances to pass all this data back and forth; but, that quickly gets ugly if not downright impossible via Axis. A much simpler, cleaner way to pass this data is via XML; specifically a string containing XML-formatted data. This is where XMLBeans makes life really easy; at the price of learning XML Schema. XML Schema is a “means for defining the structure, content and semantics of XML documents” --- see the W3C (World Wide Web Consortium) XML Schema project page for more details. A good website providing understandable reference pages and tutorials for XML Schema is www.w3schools.com/schema.
The XML request might look something like this, with two books in our shopping basket:
<basket zipcode="46835" xmlns="http://mybookstore.com/basket"> <book isbn="0201700735"> <title>The C++ Programming Language: Special Edition</title> <author>Bjarne Stroustrup</author> <year>2000</year> </book> <book isbn="0072226846"> <title>Java 2: Sun Certified Programmer & Developer for Java 2</title> <author>Kathy Sierra</author> <author>Bert Bates</author> <publisher>Osborne Certification Press</publisher> <year>2003</year> </book> </basket>
Here is the schema for the createInvoice
request. The top-level element is a basket
, which contains one or more book
elements and has a required zipcode
attribute. Each book
contains:
title
element, whose value can be any string;
author
elements, each whose value can be any string;
publisher
element, whose value can be any string;
year
element, whose value must be a 4 digit number in the range 1956--2007 (inclusive); and
isbn
attribute, whose value must be a 10 digit number, with leading zeros if necessary (e.g. 0072226846).
The value for the zipcode
attribute must be a 5 digit number, with leading zeros if necessary (e.g. 01804).
example/contract/basket.xsd
<?xml version="1.0" encoding="utf-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bb="http://mybookstore.com/basket" targetNamespace="http://mybookstore.com/basket" elementFormDefault="qualified"> <xs:element name="basket"> <xs:annotation> <xs:documentation> A basket is a non-empty set of books destined for a specific zipcode. </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="book" type="bb:book" maxOccurs="unbounded" /> </xs:sequence> <xs:attribute name="zipcode" type="bb:zipcode" use="required" /> </xs:complexType> </xs:element> <xs:complexType name="book"> <xs:annotation> <xs:documentation> A book has to have a title and one or more authors. However, the publisher and year are optional. </xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="title" type="xs:string" /> <xs:element name="author" type="xs:string" maxOccurs="unbounded" /> <xs:element name="publisher" type="xs:string" minOccurs="0" /> <xs:element name="year" type="bb:year" minOccurs="0" /> </xs:sequence> <xs:attribute name="isbn" type="bb:isbn" use="required" /> </xs:complexType> <xs:simpleType name="zipcode"> <xs:annotation> <xs:documentation> A 5 digit number with leading zeroes </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{5}"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="isbn"> <xs:annotation> <xs:documentation> A 10 digit number with leading zeroes </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{10}"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="year"> <xs:annotation> <xs:documentation> We don't sell really old books or books from the future. Note that at least the maxInclusive value must be updated each year! </xs:documentation> </xs:annotation> <xs:restriction base="xs:integer"> <xs:minInclusive value="1956" /> <xs:maxInclusive value="2007" /> </xs:restriction> </xs:simpleType> </xs:schema>
What we want back is an invoice: a list of items with the price listed for each, a subtotal, the S&H charge, and the grand total. Something like this:
<invoice zipcode="46835" xmlns="http://mybookstore.com/invoice"> <book isbn="0201700735"> <title>The C++ Programming Language: Special Edition</title> <author>Bjarne Stroustrup</author> <price>69.68</price> </book> <book isbn="0072226846"> <title>Java 2: Sun Certified Programmer & Developer for Java 2</title> <author>Kathy Sierra</author> <price>11.34</price> </book> <subtotal>81.02</subtotal> <charges>15.35</charges> <total>96.37</total> </invoice>
I know a real bookstore would need a lot more than this (what about discounts, what if something is out of stock, etc.); but this is all we want for our example. Anyway, here is the schema for the createInvoice
response. The top-level element is an invoice
, which contains one or more book
elements and pricing elements.
The invoice
has a required zipcode
attribute which must be a 5 digit number, with leading zeros if necessary (e.g. 01804).
For the invoice
, each book
contains:
title
element, whose value can be any string;
author
element, whose value can be any string (we just need the first author when printing our invoice);
price
element, whose value must be something called “money” (which I will explain shortly); and
isbn
attribute, whose value must be a 10 digit number, with leading zeros if necessary (e.g. 0072226846).
Finally, the invoice
contains three required pricing elements, subtotal
, charges
(shipping and handling charges), and total
, all of whose values must be that something called “money”. We define money
as a non-negative number which includes a decimal point and two digits after the decimal, just like we typically express dollars and cents in the United States.
example/contract/invoice.xsd
<?xml version="1.0" encoding="utf-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bi="http://mybookstore.com/invoice" targetNamespace="http://mybookstore.com/invoice" elementFormDefault="qualified"> <xs:element name="invoice"> <xs:annotation> <xs:documentation> A invoice is an itemized list of books purchased, a subtotal, the shipping charge, and the grand total. </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="book" type="bi:book" maxOccurs="unbounded" /> <xs:element name="subtotal" type="bi:money" /> <xs:element name="charges" type="bi:money" /> <xs:element name="total" type="bi:money" /> </xs:sequence> <xs:attribute name="zipcode" type="bi:zipcode" use="required" /> </xs:complexType> </xs:element> <xs:complexType name="book"> <xs:annotation> <xs:documentation> For the invoice, we only need a title and the first listed author. </xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="title" type="xs:string" /> <xs:element name="author" type="xs:string" /> <xs:element name="price" type="bi:money" /> </xs:sequence> <xs:attribute name="isbn" type="bi:isbn" use="required" /> </xs:complexType> <xs:simpleType name="zipcode"> <xs:annotation> <xs:documentation> A 5 digit number with leading zeroes </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{5}"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="isbn"> <xs:annotation> <xs:documentation> A 10 digit number with leading zeroes </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{10}"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="money"> <xs:annotation> <xs:documentation> Must be positive and no fractional pennies. </xs:documentation> </xs:annotation> <xs:restriction base="xs:decimal"> <xs:minInclusive value="0.00" /> <xs:fractionDigits value="2" /> </xs:restriction> </xs:simpleType> </xs:schema>
I realize there are a few elements in common between these two schemas and I could have put those common elements in a third schema, and included that third schema in these two. But I didn’t.
These schemas will need to be processed by the XMLBeans program scomp
. If one were to do this by hand, the equivalent command to what we have in the contract
target in the build.xml
Ant build script (see below) is:
scomp -src contract/src -out build/lib/contract.jar contract
This command processes the schemas in the contract
directory (basket.xsd
and invoice.xsd
) into several classes, which are stored in build/lib/contract.jar
. This command also instructs scomp
to output into the contract/src
directory all the Java source code for those classes (just because we are curious, not because it is needed). Note that scomp
will create the src
directory if one does not exist in contract
; however, it will not create the lib
directory in build
. Go figure.
Here is the code for the BookstoreService
class, which has only one method, createInvoice
. createInvoice
receives the basket XML as a string.
The XMLBeans paradigm is essentially that for a given top-level element, there is a “Document” class which represents the full schema instance. Contained in that “Document” class is a class representing the top-level element. So, for our basket schema, there is a BasketDocument
class containing a Basket
class. We can only get and set information from the Basket
class; the BasketDocument
class is just (to us) some necessary holder.
So in the createInvoice
method, we use a BasketDocument.Factory.parse
method to extract the basket document from the input XML string; and then we use the BasketDocument.getBasket
method to get a Basket
we can use.
Similarly, we use the InvoiceDocument.Factory.newInstance
method to create a blank invoice document (which we will eventually return ); and then we use the InvoiceDocument.addNewInvoice
method to create an Invoice
we can use.
Remember, the XMLBeans scomp
program has created all these basket and invoice classes and methods for us from our two schemas.
Next, the createInvoice
method simply copies the zip code from the Basket
to our new Invoice
.
Then, we need to access all the books placed in the basket. We use the undocumented getBookList
method instead of the getBookArray
described in the XMLBeans documentation. This List
method is a new feature of XMLBeans which (according to the comments in the source code generated by scomp
) deprecates the Array
method. I discovered it only because I was curious to see the source code scomp
generated.
For each book in the basket, the createInvoice
method simply copies the title, the first author specified, and the ISBN into a new book item in the invoice. We come up with a price and add that to the invoice book item. Notice that XMLBeans uses BigDecimal
when dealing with numeric values in the schema. This is mentioned somewhere in the XMLBeans documentation, but was not readily apparent to me and tripped me up at first.
Finally, we compute and add to the invoice the subtotal, shipping charges, and grand total. Finally, we use the InvoiceDocument.toString
method to serialize our invoice XML document so the createInvoice
method can return it.
example/src/com/mybookstore/service/BookstoreService.java
package com.mybookstore.service; import com.mybookstore.basket.BasketDocument; import com.mybookstore.basket.BasketDocument.Basket; import com.mybookstore.invoice.InvoiceDocument; import com.mybookstore.invoice.InvoiceDocument.Invoice; import org.apache.xmlbeans.*; import java.util.*; import java.math.BigDecimal; public class BookstoreService { public String createInvoice( String request_xml ) { Random generator = new Random(); String response_xml = new String(); try { // Parse the input request (BASKET) BasketDocument basket_doc = BasketDocument.Factory.parse( request_xml ); Basket mybasket = basket_doc.getBasket(); // Initialize our response (INVOICE) InvoiceDocument invoice_doc = InvoiceDocument.Factory.newInstance(); Invoice myinvoice = invoice_doc.addNewInvoice(); // Copy the zip code from the basket to the invoice String zipcode = mybasket.getZipcode(); myinvoice.setZipcode( zipcode ); // Get the list of books from the basket List<com.mybookstore.basket.Book> book_list = mybasket.getBookList(); if (book_list.isEmpty()) { return "<error>The basket is empty</error>"; } // For each book in the basket // 1. copy the title, first author, and ISBN to the invoice book list // 2. determine the price of the book (a random price under $100) int book_count = 0; double subtotal = 0.0; Iterator<com.mybookstore.basket.Book> i = book_list.iterator(); while (i.hasNext()) { com.mybookstore.basket.Book basket_book = i.next(); com.mybookstore.invoice.Book invoice_book = myinvoice.addNewBook(); invoice_book.setTitle( basket_book.getTitle() ); invoice_book.setAuthor( basket_book.getAuthorArray( 0 ) ); invoice_book.setIsbn( basket_book.getIsbn() ); int price_cents = generator.nextInt( 10000 ); double price = price_cents; price /= 100.0; BigDecimal book_price = new BigDecimal( price ).setScale( 2, BigDecimal.ROUND_HALF_UP ); invoice_book.setPrice( book_price ); subtotal += price; ++book_count; } // Set the subtotal price in the invoice BigDecimal subtotal_price = new BigDecimal( subtotal ).setScale( 2, BigDecimal.ROUND_HALF_UP ); myinvoice.setSubtotal( subtotal_price ); // Calculate the shipping charge and set it in the invoice // 1. Estimate the distance based on zip code // 2. Determine the shipping charge per book // 3. Multiply that by number of books to get total shipping charge double shipping = Double.parseDouble( zipcode ); shipping = 1.00 + (Math.abs( 80207.0 - shipping )/5000.0); shipping *= book_count; BigDecimal shipping_price = new BigDecimal( shipping ).setScale( 2, BigDecimal.ROUND_HALF_UP ); myinvoice.setCharges( shipping_price ); // Determine the grand total and set it in the invoice subtotal += shipping; BigDecimal total_price = new BigDecimal( subtotal ).setScale( 2, BigDecimal.ROUND_HALF_UP ); myinvoice.setTotal( total_price ); // Serialize the invoice into a response string response_xml = invoice_doc.toString(); } catch (Exception e) { response_xml = e.toString(); } return response_xml; } }
Here is the code for the BookstoreClient
class. It simply reads the basket from an XML file specified on the command line, sends that to the BookstoreService.createInvoice
method, and then looks at the invoice returned to report the subtotal (cost of the books), shipping, and total cost. As you look at this Java code, please remember I am a C/C++ programmer --- I am just bluffing my way through Java.
First, the client uses org.apache.axis.utils.Options
to extract the Axis-specific arguments from the command line arguments. I have not yet been able to find any documentation for a full list of command line arguments supported by Options
; however, I do know (from examples in various Axis documentation and tutorials) that there is a -lURL
argument which specifies the URL for the service to call (in our case, http://localhost/axis/services/BookstoreService
).
The remaining argument is supposed to be the path and name of an XML file containing the basket to be processed. We use java.io.File
to open the file, and then use a BasketDocument.Factory.parse
method which validates the XML while it parses it. Next, we check that the basket is not empty, though this is probably unnecessary since the schema requires at least one book element within the basket. Now we can serialize the BasketDocument
into a string that we will send to the BookstoreService
.
This client was hand-coded; I did not use the WSDL2Java capability of Axis. Doing that would hide all the nitty-gritty Service
and Call
stuff from us. For now, however, I just used the example from the tutorial and did it “the hard way.” I don’t really understand why the OperationName
uses http://com/mybookstore/service
rather than http://mybookstore.com/service
; but that’s the way the example showed it and it works.
Finally, we use the InvoiceDocument.Factory.parse
method to deserialize the returned invoice XML string, and then print out the pricing summary.
example/src/com/mybookstore/client/BookstoreClient.java
package com.mybookstore.client; import com.mybookstore.basket.BasketDocument; import com.mybookstore.basket.BasketDocument.Basket; import com.mybookstore.invoice.InvoiceDocument; import com.mybookstore.invoice.InvoiceDocument.Invoice; import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.utils.Options; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; import java.io.*; import java.util.List; public class BookstoreClient { public static void main( String [] args ) { // Process the options, primarily to extract the "-lURL" argument Options options = null; String endpointURL = null; try { options = new Options(args); endpointURL = options.getURL(); } catch (Exception e) { System.err.println( e.toString() ); return; } // The remaining argument specifies the file containing the basket XML args = options.getRemainingArgs(); if ((args == null) || (args.length < 1)) { System.err.println( "ERROR: no basket XML file specified" ); return; } // Parse the specified file into a BASKET File basketXmlFile = new File( args[0] ); if (! basketXmlFile.exists()) { System.err.println( "ERROR: " + args[0] + " does not exist" ); return; } BasketDocument request_xml = null; try { request_xml = BasketDocument.Factory.parse( basketXmlFile ); } catch (Exception e) { System.err.println( "ERROR: unable to parse " + args[0] ); System.err.println( e.toString() ); return; } Basket mybasket = request_xml.getBasket(); // Make sure the basket isn't empty List<com.mybookstore.basket.Book> book_list = mybasket.getBookList(); if (book_list.isEmpty()) { System.err.println( "ERROR: there are no books in the basket" ); return; } // Serialize the basket into a request string String request = request_xml.toString(); System.out.println( "REQUEST:" ); System.out.println( request ); // Call the BookstoreService createInvoice method with the request string String response = null; try { Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress( new java.net.URL(endpointURL) ); call.setOperationName( new QName( "http://com/mybookstore/service", "createInvoice" ) ); call.addParameter( "arg1", XMLType.XSD_STRING, ParameterMode.IN ); call.setReturnType( org.apache.axis.encoding.XMLType.XSD_STRING ); response = (String) call.invoke( new Object[] { request } ); } catch (Exception e) { System.err.println( e.toString() ); return; } System.out.println( "RESPONSE: " ); System.out.println( response ); // Parse the INVOICE from the response string InvoiceDocument response_xml = null; try { response_xml = InvoiceDocument.Factory.parse( response ); } catch (Exception e) { System.err.println( "ERROR: unable to parse response" ); return; } Invoice invoice = response_xml.getInvoice(); // I'm lazy here and just print out the subtotal, shipping, and total System.out.println( "Subtotal: " + invoice.getSubtotal().toString() ); System.out.println( " S&H: " + invoice.getCharges().toString() ); System.out.println( " Total: " + invoice.getTotal().toString() ); } }
Here are the WSDD files I use to deploy and undeploy BookstoreService as an Axis service.
example/deployment/deploy.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="BookstoreService" provider="java:RPC"> <parameter name="className" value="com.mybookstore.service.BookstoreService" /> <parameter name="allowedMethods" value="createInvoice" /> </service> </deployment>
example/deployment/undeploy.wsdd
<undeployment xmlns="http://xml.apache.org/axis/wsdd/"> <service name="BookstoreService"/> </undeployment>
Here is my rather involved Ant build script.
ant
.
ant deploy
; if anything needs building, that will be done as well. The deploy
target also takes care of stopping and restarting the Axis service within Tomcat, so that the new BookstoreService is immediately available.
ant client-test
. This makes sure everything is built, but it does not make sure the BookstoreService is deployed (after all, one might want to test what happens when that service isn’t deployed).
ant path-debug
; it displays the values of all the classpaths used.
example/build.xml
<?xml version="1.0" ?> <project name="BookstoreExample" basedir="." default="build"> <description> The master ant build file for the Bookstore Example. The following environment variables are required: CATALINA_HOME where Tomcat is installed AXIS_HOME where Axis is installed AXIS_WEBINF where the Axis WEB-INF directory is located XMLBEANS_HOME where XMLBeans is installed </description> <!-- init ======================================================== --> <target name="init"> <property environment="env" /> <echo>${ant.project.name} project</echo> <echo>${ant.version}</echo> <echo>Java version ${ant.java.version}</echo> <!-- project properties --> <property name="build" location="build" /> <property name="build.lib" location="${build}/lib" /> <property name="src" location="src" /> <property name="package.dir" value="com/mybookstore" /> <property name="package.spec" value="com.mybookstore" /> <!-- Tomcat properties and tasks --> <available property="tomcat.home" value="${env.CATALINA_HOME}" file="${env.CATALINA_HOME}" type="dir" /> <fail message="Set CATALINA_HOME in your environment" unless="tomcat.home" /> <echo>tomcat.home: ${tomcat.home}</echo> <available property="tomcat.lib" value="${tomcat.home}/server/lib" file="${tomcat.home}/server/lib/catalina-ant.jar" /> <fail message="Cannot find catalina-ant.jar in your Tomcat installation" unless="tomcat.lib" /> <property name="tomcat.url" value="http://localhost/manager" /> <property name="tomcat.uname" value="admin" /> <property name="tomcat.pword" value="secret" /> <property name="tomcat.axis.path" value="/axis" /> <path id="tomcat.classpath"> <pathelement location="${tomcat.lib}/catalina-ant.jar" /> </path> <taskdef name="tomcat.start" classname="org.apache.catalina.ant.StartTask" classpathref="tomcat.classpath" /> <taskdef name="tomcat.stop" classname="org.apache.catalina.ant.StopTask" classpathref="tomcat.classpath" /> <!-- Axis properties --> <available property="axis.home" value="${env.AXIS_HOME}" file="${env.AXIS_HOME}" type="dir" /> <fail message="Set AXIS_HOME in your environment" unless="axis.home" /> <echo>axis.home: ${axis.home}</echo> <available property="axis.webinf" value="${env.AXIS_WEBINF}" file="${env.AXIS_WEBINF}" type="dir" /> <fail message="Set AXIS_WEBINF in your environment" unless="axis.webinf" /> <echo>axis.webinfo: ${axis.webinf}</echo> <property name="axis.web.classes" value="${axis.webinf}/classes" /> <property name="axis.web.lib" value="${axis.webinf}/lib" /> <path id="axis.classpath"> <fileset dir="${axis.webinf}/lib"> <include name="**/*.jar" /> </fileset> </path> <taskdef resource="axis-tasks.properties" classpathref="axis.classpath" /> <property name="axis.server.hostname" value="localhost" /> <property name="axis.server.port" value="80" /> <property name="axis.server.url" value="http://${axis.server.hostname}:${axis.server.port}" /> <property name="axis.services.path" value="axis/services" /> <property name="axis.services.url" value="${axis.server.url}/${axis.services.path}" /> <property name="axis.admin.servlet" value="${axis.services.path}/AdminService" /> <!-- XMLBeans properties --> <available property="xmlbeans.home" value="${env.XMLBEANS_HOME}" file="${env.XMLBEANS_HOME}" type="dir" /> <fail message="Set XMLBEANS_HOME in your environment." unless="xmlbeans.home" /> <echo>xmlbeans.home: ${xmlbeans.home}</echo> <property name="xmlbeans.lib" value="${xmlbeans.home}/lib" /> <path id="xmlbeans.path"> <fileset dir="${xmlbeans.lib}" includes="*.jar" /> </path> <taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" classpathref="xmlbeans.path" /> <!-- contract properties --> <property name="contract" location="contract" /> <property name="contract.src" value="${contract}/src" /> <property name="contract.jar" value="contract.jar" /> <property name="contract.build.target" value="${build.lib}/${contract.jar}" /> <property name="contract.install.target" value="${axis.web.lib}/${contract.jar}" /> <!-- service properties --> <property name="service.name" value="BookstoreService" /> <property name="service.dir" value="${package.dir}/service" /> <property name="service.class" value="${service.dir}/${service.name}.class" /> <property name="service.build.target" value="${build}/${service.class}" /> <property name="service.install.target" value="${axis.web.classes}/${service.class}" /> <property name="deploy.config.dir" value="deployment" /> <property name="service.deploy.wsdd" value="${deploy.config.dir}/deploy.wsdd" /> <property name="service.undeploy.wsdd" value="${deploy.config.dir}/undeploy.wsdd" /> <property name="service.url" value="${axis.services.url}/${service.name}" /> <!-- client properties --> <property name="client.name" value="BookstoreClient" /> <property name="client.dir" value="${package.dir}/client" /> <property name="client.class" value="${client.dir}/${client.name}.class" /> <property name="client.spec" value="${package.spec}.client" /> <property name="client.classname" value="${client.spec}.${client.name}" /> <property name="client.xmlfile" value="data/test_basket.xml" /> <path id="client.classpath"> <path path="${build}" /> <path location="${contract.build.target}" /> <path refid="xmlbeans.path" /> <path refid="axis.classpath" /> </path> <!-- service test program properties --> <property name="service.test.name" value="BookstoreServiceTest" /> <property name="service.test.spec" value="${package.spec}.test" /> <property name="service.test.classname" value="${service.test.spec}.${service.test.name}" /> <property name="service.test.xmlfile" value="data/test_basket.xml" /> <path id="service.test.classpath"> <path location="${build}" /> <path location="${contract.build.target}" /> <path refid="xmlbeans.path" /> </path> <!-- project directory setup --> <mkdir dir="${build}" /> <mkdir dir="${build.lib}" /> <mkdir dir="${contract.src}" /> </target> <!-- clean ======================================================= --> <target name="clean" depends="init" description="Start from scratch"> <delete dir="${build}" /> <delete dir="${contract.src}" /> </target> <!-- path-debug ================================================== --> <target name="path-debug" depends="init" description="Print out the classpaths defined in init"> <property name="axis.classpath.value" refid="axis.classpath" /> <echo> axis.classpath: ${axis.classpath.value} </echo> <property name="xmlbeans.path.value" refid="xmlbeans.path" /> <echo> xmlbeans.path: ${xmlbeans.path.value} </echo> <property name="client.classpath.value" refid="client.classpath" /> <echo> client.classpath: ${client.classpath.value} </echo> <property name="service.test.classpath.value" refid="service.test.classpath" /> <echo> service.test.classpath: ${service.test.classpath.value} </echo> </target> <!-- build ======================================================= --> <target name="build" depends="init,contract,compile" description="Build the Bookstore Example service and client"> </target> <!-- contract ==================================================== --> <target name="contract" depends="init,contract.check,contract.jar" description="Use XMLBeans to process the contract XML Schemas" > </target> <target name="contract.check" depends="init"> <uptodate property="contract.notRequired" targetfile="${contract.build.target}"> <srcfiles dir="${contract}" includes="**/*.xsd" /> </uptodate> </target> <target name="contract.jar" depends="init,contract.check" unless="contract.notRequired"> <xmlbean schema="contract" destfile="${contract.build.target}" srcgendir="${contract.src}" classpathref="xmlbeans.path" javasource="1.5" /> </target> <!-- compile ===================================================== --> <target name="compile" depends="init,contract" description="Compile the service and client"> <javac srcdir="${src}" destdir="${build}"> <classpath> <path location="${contract.build.target}" /> <path refid="xmlbeans.path" /> <path refid="axis.classpath" /> </classpath> </javac> </target> <!-- deploy ====================================================== --> <target name="deploy" depends="init,contract,compile" description="Deploy the service to AXIS"> <copy file="${service.build.target}" tofile="${service.install.target}" /> <copy file="${contract.build.target}" tofile="${contract.install.target}" /> <echo>xmlfile: ${service.deploy.wsdd}</echo> <axis-admin hostname="${axis.server.hostname}" port="${axis.server.port}" failonerror="false" servletpath="${axis.admin.servlet}" xmlfile="${service.deploy.wsdd}" /> <tomcat.stop url="${tomcat.url}" username="${tomcat.uname}" password="${tomcat.pword}" path="${tomcat.axis.path}" /> <tomcat.start url="${tomcat.url}" username="${tomcat.uname}" password="${tomcat.pword}" path="${tomcat.axis.path}" /> </target> <!-- undeploy ==================================================== --> <target name="undeploy" depends="init" description="Undeploy the service"> <echo>xmlfile: ${service.undeploy.wsdd}</echo> <axis-admin hostname="${axis.server.hostname}" port="${axis.server.port}" failonerror="false" servletpath="${axis.admin.servlet}" xmlfile="${service.undeploy.wsdd}" /> <tomcat.stop url="${tomcat.url}" username="${tomcat.uname}" password="${tomcat.pword}" path="${tomcat.axis.path}" /> <delete file="${service.install.target}" failonerror="false" /> <delete file="${contract.install.target}" failonerror="false" /> <tomcat.start url="${tomcat.url}" username="${tomcat.uname}" password="${tomcat.pword}" path="${tomcat.axis.path}" /> </target> <!-- service-test ================================================ --> <target name="service-test" depends="init,compile" description="Runs the service test program"> <echo>Attempting to run ${service.test.classname}</echo> <java classname="${service.test.classname}" failonerror="false" classpathref="service.test.classpath"> <arg value="${service.test.xmlfile}" /> </java> </target> <!-- client-test ================================================= --> <target name="client-test" depends="init,compile" description="Runs the client program with test data"> <echo>Attempting to run ${client.classname}</echo> <java classname="${client.classname}" failonerror="false" classpathref="client.classpath"> <arg value="-l${service.url}" /> <arg value="${client.xmlfile}" /> </java> </target> </project>
< Web Services using Tomcat, Axis, and XMLBeans | Working With Windows | Getting rid of Nero Scout >
What we obtain too cheap, we esteem too lightly: it is dearness only that gives every thing its value.
loaded 2025-05-20 16:28:10 • last modified 2015-07-14 12:08:40 |