| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <title>Axis User's Guide</title> |
| <link href="axis.css" rel=stylesheet type=text/css> |
| </head> |
| <body > |
| |
| <center> |
| <h1> |
| <img SRC="images/axis.jpg" height=96 width=176></h1></center> |
| |
| <h1>Axis User's Guide</h1> |
| <i>1.2 Version</i> |
| <br><i>Feedback: <a href="mailto:axis-dev@ws.apache.org">axis-dev@ws.apache.org</a></i> |
| |
| <h3> |
| Table of Contents</h3> |
| |
| <ul> |
| <li> <a href="#Introduction">Introduction</a></li> |
| <li> <a href="#Installation">Installing Axis</a></li> |
| <li> <a href="#ConsumingServices">Consuming Web Services with Axis</a></li> |
| <li> <a href="#PublishingServices">Publishing Web Services with Axis</a></li> |
| <li> <a href="#DataMapping">XML <-> Java Data Mapping in Axis</a></li> |
| <li> <a href="#WSDL">Using WSDL with Axis</a></li> |
| <ul> |
| <li> <a href="#WSDL: Obtaining WSDL for deployed services">?WSDL: Obtaining |
| WSDL for deployed services</a></li> |
| <li> <a href="#WSDL2Java: Building stubs, skeletons, and data">WSDL2Java: |
| Building stubs, skeletons, and data</a></li> |
| <li> <a href="#Java2WSDL: Building WSDL from Java">Java2WSDL: Building |
| WSDL from Java</a></li> |
| </ul> |
| <li> <a href="#published interfaces">Published Interfaces</a></li> |
| <li> <a href="#newbie">Newbie Tips: Finding Your Way Around</a></li> |
| <li> <a href="#tcpmon">Appendix : Using TCPMon</a></li> |
| <li> <a href="#soapmon">Appendix : Using SOAP Monitor</a></li> |
| <li> <a href="#Glossary">Glossary</a></li> |
| </ul> |
| |
| <h2> |
| <a NAME="Introduction"></a>Introduction</h2> |
| Welcome to Axis, the third generation of Apache SOAP! |
| <h3> |
| What is SOAP?</h3> |
| |
| <p> |
| SOAP is an XML<i>-</i>based communication protocol and encoding format for inter-application |
| communication. Originally conceived by Microsoft and Userland software, it has |
| evolved through several generations; the current spec is version, |
| <a href="http://w3.org/TR/soap">SOAP 1.2</a>, though version1.1 is more |
| widespread. The W3C's <a href="http://www.w3.org/2000/xp/Group/">XML |
| Protocol working group</a> is in charge of the specification. |
| </p> |
| <p>SOAP is widely viewed as the backbone to a new generation of cross-platform |
| cross-language distributed computing applications, termed Web Services. |
| </p> |
| <h3> |
| What is Axis?</h3> |
| Axis is essentially a <i>SOAP engine</i> -- a framework for |
| constructing SOAP processors such as |
| clients, servers, gateways, etc. |
| The current version of Axis is written in Java, but |
| a C++ implementation of the client side of Axis is being developed. |
| <p> |
| But Axis isn't just a SOAP engine -- it also includes: |
| <ul> |
| <li> a simple stand-alone server, |
| <li> a server which plugs into servlet engines such as Tomcat, |
| <li> extensive support for the <i>Web Service Description Language (WSDL)</i>, |
| <li> emitter tooling that generates Java classes from WSDL. |
| <li> some sample programs, and |
| <li> a tool for monitoring TCP/IP packets. |
| </ul> |
| <p> |
| Axis is the third generation of Apache SOAP (which began at IBM as "SOAP4J"). |
| In late 2000, the committers of Apache SOAP v2 began discussing |
| how to make the engine much more flexible, configurable, and able to handle |
| both SOAP and the upcoming XML Protocol specification from the W3C. |
| <p>After a little while, it became clear that a ground-up rearchitecture |
| was required. Several of the v2 committers proposed very similar designs, |
| all based around configurable "chains" of message "handlers" which would |
| implement small bits of functionality in a very flexible and composable |
| manner. |
| <p>After months of continued discussion and coding |
| effort in this direction, Axis now delivers the following key features: |
| <ul> |
| <li> <b>Speed.</b> Axis uses SAX (event-based) parsing to acheive significantly |
| greater speed than earlier versions of Apache SOAP.</li> |
| <li> <b>Flexibility.</b> The Axis architecture gives the developer complete |
| freedom to insert extensions into the engine for custom header processing, |
| system management, or anything else you can imagine.</li> |
| <li> <b>Stability.</b> Axis defines a set of <a href="#published interfaces">published |
| interfaces</a> which change relatively slowly compared to the rest of Axis.</li> |
| <li> <b>Component-oriented deployment.</b> You can easily define reusable networks |
| of Handlers to implement common patterns of processing for your applications, |
| or to distribute to partners.</li> |
| <li> <b>Transport framework.</b> We have a clean and simple abstraction for |
| designing transports (i.e., senders and listeners for SOAP over various protocols |
| such as SMTP, FTP, message-oriented middleware, etc), and the core of the |
| engine is completely transport-independent.</li> |
| <li><b>WSDL support.</b> Axis supports the <a href="http://www.w3.org/TR/wsdl">Web |
| Service Description Language</a>, version 1.1, which allows you to easily |
| build stubs to access remote services, and also to automatically export machine-readable |
| descriptions of your deployed services from Axis.</li> |
| </ul> |
| <p> |
| We hope you enjoy using Axis. Please note that this is an open-source effort |
| - if you feel the code could use some new features or fixes, please get |
| involved and lend a hand! The Axis developer community welcomes your |
| participation. And in case you're wondering what <i>Axis</i> stands for, |
| it's <b>A</b>pache E<b>X</b>tensible <b>I</b>nteraction <b>S</b>ystem - |
| a fancy way of implying it's a very configurable SOAP engine. |
| <h4> |
| <b>Let us know what you think!</b></h4> |
| Please send feedback about the package to "<a href="mailto:axis-user@ws.apache.org">axis-user@ws.apache.org</a>". |
| Also, Axis is registered in <a href="http://nagoya.apache.org/bugzilla">bugzilla</a>, |
| the Apache bug tracking and feature-request database. |
| <h3> |
| What's in this release?</h3> |
| This release includes the following features: |
| <ul> |
| <li> SOAP 1.1/1.2 compliant engine</li> |
| <li> Flexible configuration / deployment system</li> |
| <li> Support for "drop-in" deployment of SOAP services (JWS)</li> |
| <li> Support for all basic types, and a type mapping system for defining new |
| serializers/deserializers</li> |
| <li> Automatic serialization/deserialization of Java Beans, including customizable |
| mapping of fields to XML elements/attributes</li> |
| <li> Automatic two-way conversions between Java Collections and SOAP Arrays</li> |
| <li> Providers for RPC and message based SOAP services</li> |
| <li> Automatic WSDL generation from deployed services</li> |
| <li> WSDL2Java tool for building Java proxies and skeletons from WSDL documents</li> |
| <li> Java2WSDL tool for building WSDL from Java classes.</li> |
| <li> Preliminary security extensions, which can integrate with Servlet 2.2 security/roles</li> |
| <li>Support for session-oriented services, via HTTP cookies or transport-independent |
| SOAP headers</li> |
| <li>Preliminary support for the <b>SOAP with Attachments</b> specification</li> |
| <li> An EJB provider for accessing EJB's as Web Services</li> |
| <li> HTTP servlet-based transport</li> |
| <li> JMS based transport</li> |
| <li> Standalone version of the server (with HTTP support)</li> |
| <li> Examples, including a client and server for the SoapBuilders community |
| interoperability tests and experimental TCP, JMS, and file-based transports.</li> |
| </ul> |
| |
| <h3> What's still to do?</h3> |
| <p>Please click for <a href="to-do.html">a list of what we think needs doing</a> |
| - and please consider helping out if you're interested & able!</p> |
| |
| <h2> |
| <a NAME="Installation"></a>Installing Axis and Using this Guide</h2> |
| See the <a href="install.html">Axis Installation Guide</a> |
| for instructions on installing Axis as a web application on your J2EE server. |
| <p>Before running the examples in this guide, you'll need to make sure |
| that your CLASSPATH includes |
| (Note: If you build Axis from a CVS checkout, |
| these will be in xml-axis/java/build/lib instead of axis-1_2/lib): |
| <ul> |
| <li>axis-1_2/lib/axis.jar</li> |
| <li>axis-1_2/lib/jaxrpc.jar</li> |
| <li>axis-1_2/lib/saaj.jar</li> |
| <li>axis-1_2/lib/commons-logging.jar</li> |
| <li>axis-1_2/lib/commons-discovery.jar</li> |
| <li>axis-1_2/lib/wsdl4j.jar</li> |
| <li>axis-1_2/ <i><font color="#9966FF">(for the sample code)</font></i></li> |
| <li>A JAXP-1.1 compliant XML parser such as Xerces or Crimson. We recommend |
| <A href="http://xml.apache.org/xerces2-j/">Xerces</A>, as it is the one |
| that the product has been tested against.</li> |
| </ul> |
| <h2> |
| <a NAME="ConsumingServices"></a>Consuming Web Services with Axis</h2> |
| |
| <h3> |
| Basics - Getting Started</h3> |
| Let's take a look at an example Web Service client that will call the <b>echoString</b> |
| method on the public Axis server at Apache. |
| <pre class="example">1 import org.apache.axis.client.Call; |
| 2 import org.apache.axis.client.Service; |
| 3 import javax.xml.namespace.QName; |
| 4 |
| 5 public class TestClient { |
| 6 public static void main(String [] args) { |
| 7 try { |
| 8 String endpoint = |
| 9 "http://nagoya.apache.org:5049/axis/services/echo"; |
| 10 |
| 11 Service service = new Service(); |
| 12 Call call = (Call) service.createCall(); |
| 13 |
| 14 call.setTargetEndpointAddress( new java.net.URL(endpoint) ); |
| 15 call.setOperationName(new QName("<font color="#009933">http://soapinterop.org/</font>", "<font color="#993333">echoString</font>")); |
| 16 |
| 17 String ret = (String) call.invoke( new Object[] { "<font color="#CC00CC">Hello!</font>" } ); |
| 18 |
| 19 System.out.println("Sent 'Hello!', got '" + ret + "'"); |
| 20 } catch (Exception e) { |
| 21 System.err.println(e.toString()); |
| 22 } |
| 23 } |
| 24 }</pre> |
| (You'll find this file in <a href="../samples/userguide/example1/TestClient.java">samples/userguide/example1/TestClient.java</a>) |
| <p>Assuming you have a network connection active, this program can be run |
| as follows: |
| <pre class="example">% java samples.userguide.example1.TestClient |
| Sent 'Hello!', got 'Hello!' |
| %</pre> |
| So what's happening here? On lines 11 and 12 we create new Service and |
| Call objects. These are the standard JAX-RPC objects that are used to store |
| metadata about the service to invoke. On line 14, we set up our endpoint |
| URL - this is the destination for our SOAP message. On line 15 we define |
| the operation (method) name of the Web Service. And on line 17 we actually invoke |
| the desired service, passing in an array of parameters - in this case just |
| one String. |
| <p>You can see what happens to the arguments by looking at the SOAP request that |
| goes out on the wire (look at the colored sections, and notice they match the |
| values in the call above): |
| <pre class="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| <SOAP-ENV:Body> |
| <ns1:<b><font color="#993333">echoString</font></b> xmlns:ns1="<b><font color="#009933">http://soapinterop.org/</font></b>"> |
| <arg0 xsi:type="xsd:string"><b><font color="#CC00CC">Hello!</font></b></arg0> |
| </ns1:echoString> |
| </SOAP-ENV:Body> |
| </SOAP-ENV:Envelope></pre> |
| <p>The String argument is automatically serialized into XML, and the server |
| responds with an identical String, which we deserialize and print.</p> |
| <p><i>Note: To actually watch the XML flowing back and forth between a |
| SOAP client and server, you can use the included <a href="#tcpmon">tcpmon</a> tool or <a href="#soapmon">SOAP monitor</a> tool. See the appendix |
| for an overview.</i></p> |
| <h3>Naming Parameters</h3> |
| In the above example, you can see that Axis automatically names the XML-encoded |
| arguments in the SOAP message "arg0", "arg1", etc. (In this case there's just |
| "arg0") If you want to change this, it's easy! Before calling <tt>invoke()</tt> |
| you need to call <tt>addParameter</tt> for each parameter and <tt>setReturnType</tt> for the return, like so: |
| <pre class="example"> call.addParameter("testParam", |
| org.apache.axis.Constants.XSD_STRING, |
| javax.xml.rpc.ParameterMode.IN); |
| call.setReturnType(org.apache.axis.Constants.XSD_STRING); </pre> |
| This will assign the name <b>testParam</b> to the 1st (and only) parameter |
| on the invoke call. This will also define the type of the parameter (<tt>org.apache.axis.Constants.XSD_STRING</tt>) |
| and whether it is an input, output or inout parameter - in this case its |
| an input parameter. Now when you run the program you'll get a message that |
| looks like this: |
| <pre class="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| <SOAP-ENV:Body> |
| <ns1:echoString xmlns:ns1="http://soapinterop.org/"> |
| <<font color="#CC00CC">testParam</font> xsi:type="xsd:string">Hello!</<font color="#CC00CC">testParam</font>> |
| </ns1:echoString> |
| </SOAP-ENV:Body> |
| </SOAP-ENV:Envelope></pre> |
| Note that the param is now named "testParam" as expected. |
| <h3>Interoperating with "untyped" servers</h3> |
| In the above examples, we've been casting the return type of invoke(), |
| which is Object, to the appropriate "real" type - for instance, we know |
| that the echoString method returns a String, so we expect to get one back |
| from client.invoke(). Let's take a moment and investigate how this happens, |
| which sheds light on a potential problem (to which, of course, we have |
| a solution - so don't fret :)). |
| <p>Here's what a typical response might look like to the echoString method: </p> |
| <pre class="xml"><?xml version="1.0" encoding="UTF-8"?><br> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| <SOAP-ENV:Body> |
| <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/"> |
| <result <font color="#FF0000">xsi:type="xsd:string"</font>>Hello!</result> |
| </ns1:echoStringResponse> |
| </SOAP-ENV:Body> |
| </SOAP-ENV:Envelope></pre> |
| <p>Take a look at the section which we've highlighted in <font color="#FF0000">red</font> |
| - that attribute is a schema <b>type declaration</b>, which Axis uses to figure |
| out that the contents of that element are, in this case, deserializable into a |
| Java String object. Many toolkits put this kind of explicit typing information |
| in the XML to make the message "self-describing". On the other hand, some toolkits |
| return responses that look like this: </p> |
| <pre class="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| <SOAP-ENV:Body> |
| <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/"> |
| <result>Hello, I'm a string!</result> |
| </ns1:echoStringResponse> |
| </SOAP-ENV:Body> |
| </SOAP-ENV:Envelope></pre> |
| <p>There's no type in the message, so how do we know what Java object we should |
| deserialize the <result> element into? The answer is <b>metadata</b> |
| - data about data. In this case, we need a <b>description</b> of the service |
| that tells us what to expect as the return type. Here's how to do it on |
| the client side in Axis:</p> |
| <pre class="example"> call.setReturnType( org.apache.axis.Constants.XSD_STRING );</pre> |
| <p>This method will tell the Axis client that if the return element is not typed |
| then it should act as if the return value has an xsi:type attribute set to the |
| predefined SOAP String type. (You can see an example of this in action in the |
| interop echo-test client - samples/echo/TestClient.java.) </p> |
| <p>There is also a similar method which allows you to specify the Java class of |
| the expected return type:</p> |
| <pre class="example">call.setReturnClass(String.class);</pre> |
| <p>OK - so now you know the basics of accessing SOAP services as a client. |
| But how do you publish your own services? |
| <h2> |
| <a NAME="PublishingServices"></a>Publishing Web Services with Axis</h2> |
| Let's say we have a simple class like the following: |
| <pre class="example">public class Calculator { |
| public int add(int i1, int i2) |
| { |
| return i1 + i2; |
| } |
| |
| public int subtract(int i1, int i2) |
| { |
| return i1 - i2; |
| } |
| }</pre> |
| (You'll find this very class in <a href="../samples/userguide/example2/Calculator.java">samples/userguide/example2/Calculator.java</a>.) |
| <p>How do we go about making this class available via SOAP? There are a |
| couple of answers to that question, but we'll start with the easiest way |
| Axis provides to do this, which takes almost no effort at all! |
| <h3> |
| JWS (Java Web Service) Files - Instant Deployment</h3> |
| OK, here's step 1 : copy the above .java file into your webapp directory, |
| and rename it "Calculator.jws". So you might do something like this: |
| <pre>% copy Calculator.java <i><font color="#0000FF"><your-webapp-root></font></i>/axis/Calculator.jws</pre> |
| Now for step 2... hm, wait a minute. You're done! You should now be able |
| to access the service at the following URL (assuming your Axis web application |
| is on port 8080): |
| <p><a href="http://localhost:8080/axis/Calculator.jws">http://localhost:8080/axis/Calculator.jws</a> |
| <p>Axis automatically locates the file, compiles the class, and converts |
| SOAP calls correctly into Java invocations of your service class. Try it |
| out - there's a calculator client in samples/userguide/example2/CalcClient.java, |
| which you can use like this: |
| <pre class="example">% java samples.userguide.example2.CalcClient -p8080 add 2 5 |
| Got result : 7 |
| % java samples.userguide.example2.CalcClient -p8080 subtract 10 9 |
| Got result : 1 |
| %</pre> |
| (Note that you may need to replace the "-p8080" with whatever port your |
| J2EE server is running on) |
| <p> |
| <i><b>Important:</b></i> JWS web services are intended for simple web services. |
| You cannot use packages in the pages, and as the code is compiled at run |
| time you can not find out about errors until after deployment. |
| Production quality web services should use Java classes with custom |
| deployment. |
| |
| <h3> |
| Custom Deployment - Introducing WSDD</h3> |
| JWS files are great quick ways to get your classes out there as Web Services, |
| but they're not always the best choice. For one thing, you need the source code |
| - there might be times when you want to expose a pre-existing class on your system |
| without source. Also, the amount of configuration you can do as to how the service |
| gets accessed is pretty limited - you can't specify custom type mappings, or control |
| which Handlers get invoked when people are using your service. <i>(Note for the |
| future : the Axis team, and the Java SOAP community at large, are thinking about |
| ways to be able to embed this sort of metadata into your source files if desired |
| - stay tuned!)</i> |
| <h4> |
| <a NAME="descriptors"></a>Deploying via descriptors</h4> |
| <p>To really use the flexibility available to you in Axis, you should get |
| familiar with the Axis <b>Web Service Deployment Descriptor (WSDD)</b> |
| format. A deployment descriptor contains a bunch of things you want to |
| "deploy" into Axis - i.e. make available to the Axis engine. The most common |
| thing to deploy is a Web Service, so let's start by taking a look at a |
| deployment descriptor for a basic service (this file is <a href="../samples/userguide/example3/deploy.wsdd">samples/userguide/example3/deploy.wsdd</a>):</p> |
| <pre class="example"><deployment xmlns="http://xml.apache.org/axis/wsdd/" |
| xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> |
| <service name="MyService" provider="java:RPC"> |
| <parameter name="className" value="samples.userguide.example3.MyService"/> |
| <parameter name="allowedMethods" value="*"/> |
| </service> |
| </deployment></pre> |
| Pretty simple, really - the outermost element tells the engine that this is a |
| WSDD deployment, and defines the "java" namespace. Then the service element actually |
| defines the service for us. A service is a <b>targeted chain</b> (see the <a href="architecture-guide.html">Architecture |
| Guide</a>), which means it may have any/all of: a request flow, a pivot Handler |
| (which for a service is called a "provider"), and a response flow. In this case, |
| our provider is "java:RPC", which is built into Axis, and indicates a Java RPC |
| service. The actual class which handles this is <b>org.apache.axis.providers.java.RPCProvider</b>. |
| We'll go into more detail later on the different styles of services and their |
| providers. |
| <p>We need to tell the RPCProvider that it should instantiate and call the correct |
| class (e.g. samples.userguide.example3.MyService), and we do so by including |
| <parameter> tags, giving the service one parameter to configure the class |
| name, and another to tell the engine that any public method on that class may |
| be called via SOAP (that's what the "*" means; we could also have restricted |
| the SOAP-accessible methods by using a space or comma separated list of available |
| method names). |
| <h4>Advanced WSDD - specifying more options</h4> |
| <p>WSDD descriptors can also contain other information about services, and also |
| other pieces of Axis called "Handlers" which we'll cover in a later |
| section. |
| <h5>Scoped Services</h5> |
| <p>Axis supports scoping service objects (the actual Java objects which implement |
| your methods) three ways. "Request" scope, the default, will create |
| a new object each time a SOAP request comes in for your service. "Application" |
| scope will create a singleton shared object to service <b>all</b> requests. |
| "Session" scope will create a new object for each session-enabled |
| client who accesses your service. To specify the scope option, you add a <parameter> |
| to your service like this (where "<i><font color="#FF0000">value</font></i>" |
| is request, session, or application):</p> |
| <pre class="xml"><service name="MyService"...> |
| <parameter name="scope" value="<font color="#FF0000"><i>value</i></font>"/> |
| ... |
| </service></pre> |
| <h4>Using the AdminClient</h4> |
| Once we have this file, we need to send it to an Axis server in order to actually |
| deploy the described service. We do this with the AdminClient, or the "org.apache.axis.client.AdminClient" |
| class. If you have deployed Axis on a server other than Tomcat, you may need to |
| use the -p <em><port></em> argument. The default port is 8080. |
| A typical invocation of the AdminClient looks like this: |
| <pre class="example">% java org.apache.axis.client.AdminClient deploy.wsdd |
| <Admin>Done processing</Admin></pre> |
| This command has now made our service accessible via SOAP. Check it out |
| by running the Client class - it should look like this: |
| <pre class="example">% java samples.userguide.example3.Client -lhttp://localhost:8080/axis/services/MyService "test me!" |
| You typed : test me! |
| %</pre> |
| If you want to prove to yourself that the deployment really worked, try |
| undeploying the service and calling it again. There's an "undeploy.wsdd" |
| file in the example3/ directory which you can use just as you did the deploy.wsdd |
| file above. Run the AdminClient on that file, then try the service |
| Client again and see what happens. |
| <p>You can also use the AdminClient to get a listing of all the deployed |
| components in the server: |
| <pre class="example">% java org.apache.axis.client.AdminClient list |
| <big XML document returned here></pre> |
| In there you'll see services, handlers, transports, etc. Note that this |
| listing is an exact copy of the server's "server-config.wsdd" file, which |
| we'll talk about in more detail a little later. |
| <h4> |
| More deployment - Handlers and Chains</h4> |
| Now let's start to explore some of the more powerful features of the Axis |
| engine. Let's say you want to track how many times your service has been |
| called. We've included a sample handler in the samples/log directory to |
| do just this. To use a handler class like this, you first need to deploy |
| the Handler itself, and then use the name that you give it in deploying |
| a service. Here's a sample deploy.wsdd file (this is example 4 in samples/userguide): |
| <pre class="example"><deployment xmlns="http://xml.apache.org/axis/wsdd/" |
| xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> |
| <!-- define the logging handler configuration --> |
| <handler name="track" type="java:samples.userguide.example4.LogHandler"> |
| <parameter name="filename" value="MyService.log"/> |
| </handler> |
| |
| <!-- define the service, using the log handler we just defined --> |
| <service name="LogTestService"<b> </b>provider="java:RPC"> |
| <requestFlow> |
| <handler type="track"/> |
| </requestFlow> |
| |
| <parameter name="className" value="samples.userguide.example4.Service"/> |
| <parameter name="allowedMethods" value="*"/> |
| </service> |
| </deployment></pre> |
| <p>The first section defines a Handler called "track" that is implemented |
| by the class samples.userguide.example4.LogHandler. We give this Handler |
| an option to let it know which file to write its messages into. |
| <p>Then we define a service, LogTestService, which is an RPC service just |
| like we saw above in our first example. The difference is the <requestFlow> |
| element inside the <service> - this indicates a set of Handlers that |
| should be invoked when the service is invoked, before the provider. By |
| inserting a reference to "track", we ensure that the message will be logged |
| each time this service is invoked. |
| <h4> |
| Remote Administration</h4> |
| Note that by default, the Axis server is configured to only accept administration |
| requests from the machine on which it resides - if you wish to enable remote |
| administration, you must set the "enableRemoteAdmin" property of the AdminService |
| to <b>true</b>. To do this, find the "server-config.wsdd" file in your |
| webapp's WEB-INF directory. In it, you'll see a deployment for the AdminService. |
| Add an option as follows: |
| <pre class="xml"><service name="AdminService" provider="java:MSG"> |
| <parameter name="className" value="org.apache.axis.util.Admin"/> |
| <parameter name="allowedMethods" value="*"/> |
| <b><parameter name="enableRemoteAdmin" value="true"/> |
| </b></service></pre> |
| <p><b>WARNING: enabling remote administration may give unauthorized parties |
| access to your machine. If you do this, please make sure to add security |
| to your configuration!</b> |
| <h3>Service Styles - RPC, Document, Wrapped, and Message</h3> |
| <p>There are four "styles" of service in Axis. <b>RPC</b> services |
| use the SOAP RPC conventions, and also the SOAP "section 5" encoding. |
| <b>Document</b> services do not use any encoding (so in particular, you won't |
| see multiref object serialization or SOAP-style arrays on the wire) but DO still |
| do XML<->Java databinding. <b>Wrapped</b> services are just like document |
| services, except that rather than binding the entire SOAP body into one big |
| structure, they "unwrap" it into individual parameters. <b>Message</b> |
| services receive and return arbitrary XML in the SOAP Envelope without any type |
| mapping / data binding. If you want to work with the raw XML of the incoming |
| and outgoing SOAP Envelopes, write a message service.</p> |
| <h4>RPC services</h4> |
| RPC services are the default in Axis. They are what you get when you deploy services |
| with <service ... provider="java:RPC"> or <service ... style="RPC">. |
| RPC services follow the SOAP RPC and encoding rules, which means that the XML |
| for an RPC service will look like the "echoString" example above - each |
| RPC invocation is modeled as an outer element which matches the operation name, |
| containing inner elements each of which maps to a parameter of the operation. |
| Axis will deserialize XML into Java objects which can be fed to your service, |
| and will serialize the returned Java object(s) from your service back into XML. |
| Since RPC services default to the soap section 5 encoding rules, objects will |
| be encoded via "multi-ref" serialization, which allows object graphs |
| to be encoded. (See the SOAP spec for more on multi-ref serialization.) |
| <h4>Document / Wrapped services </h4> |
| <p>Document services and wrapped services are similar in that neither uses the |
| SOAP encoding for data; it's just plain old XML schema. In both cases, however, |
| Axis still "binds" Java representations to the XML (see the <a href="#DataMapping">databinding</a> |
| section for more), so you end up dealing with Java objects, not directly with |
| XML constructs.</p> |
| <p>A good place to start in describing the difference between document and wrapped |
| services is with a sample SOAP message containing a purchase order:</p> |
| <pre class="xml"><soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/" |
| xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> |
| <soap:Body> |
| <myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO"> |
| <item>SK001</item> |
| <quantity>1</quantity> |
| <description>Sushi Knife</description> |
| </myNS:PurchaseOrder> |
| </soap:Body> |
| </soap:Envelope> |
| </pre> |
| <p>The relevant schema for the PurchaseOrder looks like this:</p> |
| <pre class="xml"><schema targetNamespace="http://commerce.com/PO"> |
| <complexType name="POType"> |
| <sequence> |
| <element name="item" type="xsd:string"/> |
| <element name="quantity" type="xsd:int"/> |
| <element name="description" type="xsd:string"/> |
| </sequence> |
| </complexType> |
| <element name="PurchaseOrder" type="POType"/> |
| </deployment></pre> |
| <p>For a <b>document</b> style service, this would map to a method like this:</p> |
| <p class="example">public void method(PurchaseOrder po)</p> |
| <p>In other words, the ENTIRE <PurchaseOrder> element would be handed to |
| your method as a single bean with three fields inside it. On the other hand, |
| for a <b>wrapped</b> style service, it would map to a method like this:</p> |
| <p class="example">public void purchaseOrder(String item, int quantity, String |
| description)</p> |
| <p>Note that in the "wrapped" case, the <PurchaseOrder> element |
| is a "wrapper" (hence the name) which only serves to indicate the |
| correct operation. The arguments to our method are what we find when we "unwrap" |
| the outer element and take each of the inner ones as a parameter.</p> |
| <p>The document or wrapped style is indicated in WSDD as follows:</p> |
| <p><span class="example"><service ... style="document"></span> |
| for document style<br> |
| <span class="example"><service ... style="wrapped"></span> for |
| wrapped style</p> |
| <p>In most cases you won't need to worry about document or wrapped services if |
| you are starting from a WSDL document (<a href="#WSDL">see below</a>).</p> |
| <h4>Message services</h4> |
| <p>Finally, we arrive at "Message" style services, which should be used |
| when you want Axis to step back and let your code at the actual XML instead |
| of turning it into Java objects. There are four valid signatures for your message-style |
| service methods:</p> |
| <p><code>public Element [] method(Element [] bodies);</code><code><br> |
| public SOAPBodyElement [] method (SOAPBodyElement [] bodies);</code><code><br> |
| public Document method(Document body);<br> |
| public void method(SOAPEnvelope req, SOAPEnvelope resp);</code> </p> |
| <p>The first two will pass your method arrays of either DOM Elements or SOAPBodyElements |
| - the arrays will contain one element for each XML element inside the <soap:body> |
| in the envelope.</p> |
| <p>The third signature will pass you a DOM Document representing the <soap:body>, |
| and expects the same in return.</p> |
| <p>The fourth signature passes you two SOAPEnvelope objects representing the request |
| and response messages. This is the signature to use if you need to look at or |
| modify headers in your service method. Whatever you put into the response envelope |
| will automatically be sent back to the caller when you return. Note that the |
| response envelope may already contain headers which have been inserted by other |
| Handlers.</p> |
| <p><b>Message Example</b></p> |
| <p>A sample message service can be found in <a href="../samples/message/MessageService.java">samples/message/MessageService.java</a>. |
| The service class, <code>MessageService</code>, has one public method, <code>echoElements</code>, |
| which matches the first of the three method signatures above:</p> |
| <pre class="example">public Element[] echoElements(Element [] elems) </pre> |
| <p>The <code>MsgProvider</code> handler calls the method with an array<code></code> |
| of <code>org.w3c.dom.Element</code> objects that correspond to the immediate |
| children of the incoming message's SOAP Body. Often, this array will contain |
| a single Element (perhaps the root element of some XML document conforming to |
| some agreed-upon schema), but the SOAP Body can handle any number of children. |
| The method returns an <code>Element[]</code> array to be returned in the SOAP |
| body of the response message.</p> |
| <p>Message services must be deployed with a WSDD file. Here is the full WSDD for |
| the <code>MessageService</code> class:</p> |
| <pre class="XML"> |
| <deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/" |
| xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" |
| xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"> |
| <service name="MessageService" <font color="#FF0000">style="message"</font>> |
| <parameter name="className" value="samples.message.MessageService"/> |
| <parameter name="allowedMethods" value="echoElements"/> |
| </service><br></deployment></pre> |
| <p>Note that the "style" attribute is different from the RPC deployment |
| example. The "message" style tells Axis that this service is to be |
| handled by <code>org.apache.axis.providers.java.MsgProvider</code> rather than |
| <code>org.apache.axis.providers.java.RPCProvider</code>. </p> |
| <p>You can test this service by deploying it, then running samples.message.TestMsg |
| (look at the source to see what the test driver does).</p> |
| <h2><a NAME="DataMapping"></a>XML <-> Java Data Mapping in Axis</h2> |
| <h3>How your Java types map to SOAP/XML types</h3> |
| |
| Interoperability, <i>interop</i>, is an ongoing challenge |
| between SOAP implementations. If you want your service to work with other platforms |
| and implementations, you do need to understand the issues. There are some |
| <a href="reading.html#interop">external articles</a> on the subject that act |
| as a good starting place. |
| |
| The basic mapping between Java types and WSDL/XSD/SOAP in Axis is determined by |
| the JAX-RPC specification. Read chapters 4 and 5 of the |
| <a href="http://java.sun.com/xml/jaxrpc/"> |
| specification</a> to fully understand how things are converted. Here are |
| some of the salient points. |
| |
| |
| <h4>Standard mappings from WSDL to Java</h4> |
| <table> |
| <tr><td>xsd:base64Binary </td><td><tt>byte[]</tt></td></tr> |
| <tr><td>xsd:boolean </td><td><tt>boolean</tt></td></tr> |
| <tr><td>xsd:byte </td><td><tt>byte</tt></td></tr> |
| <tr><td>xsd:dateTime </td><td><tt>java.util.Calendar</tt></td></tr> |
| <tr><td>xsd:decimal </td><td><tt>java.math.BigDecimal</tt></td></tr> |
| <tr><td>xsd:double </td><td><tt>double</tt></td></tr> |
| <tr><td>xsd:float </td><td><tt>float</tt></td></tr> |
| <tr><td>xsd:hexBinary </td><td><tt>byte[]</tt></td></tr> |
| <tr><td>xsd:int</td><td><tt> int</tt></td></tr> |
| <tr><td>xsd:integer</td><td><tt>java.math.BigInteger</tt></td></tr> |
| <tr><td>xsd:long </td><td><tt>long</tt></td></tr> |
| <tr><td>xsd:QName </td><td><tt>javax.xml.namespace.QName</tt></td></tr> |
| <tr><td>xsd:short </td><td><tt>short</tt></td></tr> |
| <tr><td>xsd:string</td><td><tt>java.lang.String</tt></td></tr> |
| </table> |
| <p> If the WSDL says that an object can be <tt>nillable</tt>, that is the caller |
| may choose to return a value of <tt>nil</tt>, then the primitive data types |
| are replaced by their wrapper classes, such as Byte, Double, Boolean, etc. |
| <h4>SOAP Encoding Datatypes</h4> |
| <p> Alongside the XSD datatypes are the SOAP 'Section 5' datatypes that are all |
| nillable, and so only ever map to the wrapper classes. These types exist because |
| they all support the "ID" and "HREF" attributes, and so |
| will be used when in an RPC-encoded context to support multi-ref serialization. |
| |
| |
| <h3>Exceptions</h3> |
| |
| This is an area which causes plenty of confusion, and indeed, the author |
| of this section is not entirely sure how everything works, especially |
| from an interop perspective. This means treat this section as |
| incomplete and potentially inaccurate. See also section 5.5.5 and |
| chapter 14 in the JAX-RPC specification |
| |
| <h4>RemoteExceptions map to SOAP Faults</h4> |
| |
| If the server method throws a <tt>java.rmi.RemoteException</tt> then |
| this will be mapped into a SOAP Fault. The <tt>faultcode</tt> of this will contain |
| the classname of the fault. The recipient is expected to deserialize the |
| body of the fault against the classname. |
| |
| <p> |
| |
| Obviously, if the recipient does not know how to create an instance of |
| the received fault, this mechanism does not work. Unless you include |
| information about the exception class in the WSDL description of the |
| service, or sender and receiver share the implementation, |
| you can only reliably throw <tt>java.rmi.RemoteException</tt> |
| instances, rather than subclasses. |
| |
| <p> |
| |
| When an implementation in another language receives such an exception, |
| it should see the name of the class as the faultCode, but still be left |
| to parse the body of the exception. You need to experiment to find out |
| what happens there. |
| |
| <h4>Exceptions are represented as <tt>wsdl:fault</tt> elements</h4> |
| |
| If a method is marked as throwing an <tt>Exception</tt> that is not |
| an instance or a subclass of <tt>java.rmi.RemoteException</tt>, then |
| things are subtly different. The exception is no longer a SOAP Fault, but |
| described as a <tt>wsdl:fault</tt> in the WSDL of the method. |
| |
| According to the JAX-RPC specification, your subclass of Exception |
| must have accessor methods to access all the fields in the object to be |
| marshalled <i>and</i> a constructor that takes as parameters all the |
| same fields (i.e, arguments of the same name and type). This is a kind of |
| immutable variant of a normal <a href="http://java.sun.com/products/javabeans">JavaBean</a>. The fields in the object must be |
| of the datatypes that can be reliably mapped into WSDL. |
| |
| <p> |
| |
| If your exception meets this specification, then the WSDL describing the |
| method will describe the exception too, enabling callers to create stub |
| implementations of the exception, regardless of platform. |
| |
| <p> |
| |
| Again, to be sure of interoperability, you need to be experiment a bit. |
| Remember, the calling language may not have the notion of Exceptions, or |
| at least not be as rigorous as Java in the rules as to how exceptions |
| must be handled. |
| |
| <h3>What Axis can send via SOAP with restricted Interoperability</h3> |
| |
| |
| <h5>Java Collections</h5> |
| |
| Some of the Collection classes, such as <tt>Hashtable</tt>, do have |
| serializers, but there is no formal interoperability with other SOAP |
| implementations, and nothing in the SOAP specifications which covers |
| complex objects. The most reliable way to send aggregate objects is to |
| use arrays. In particular, .NET cannot handle them, though many Java SOAP |
| implementations can marshall and unmarshall hash tables. |
| |
| |
| <h3>What Axis can not send via SOAP</h3> |
| |
| |
| <h5>Arbitrary Objects without Pre-Registration</h5> |
| |
| You cannot send arbitrary Java objects over the wire and expect them to |
| be understood at the far end. With RMI you can send and receive |
| <tt>Serializable</tt> Java objects, but that is because you are running |
| Java at both ends. <b>Axis will only send objects for which there is a |
| registered Axis serializer.</b> This document shows below how to use |
| the BeanSerializer to serialize any class that follows the JavaBean |
| pattern of accessor and mutator. To serve up objects you must either |
| register your classes with this BeanSerializer, or there must be |
| serialization support built in to Axis. |
| |
| |
| <h5>Remote References</h5> |
| |
| Remote references are neither part of the SOAP specification, nor the JAX-RPC |
| specification. You cannot return some object reference and expect the |
| caller to be able to use it as an endpoint for SOAP calls or as a |
| parameter in other calls. Instead you must use some other reference |
| mechanism, such as storing them in a <tt>HashMap</tt> with numeric or |
| string keys that can be passed over the wire. |
| |
| |
| <h3>Encoding Your Beans - the BeanSerializer</h3> |
| Axis includes the ability to serialize/deserialize, without writing any |
| code, arbitrary Java classes which follow the standard <a href="http://java.sun.com/products/javabeans">JavaBean</a> pattern |
| of get/set accessors. All you need to do is tell Axis which Java classes |
| map to which XML Schema types. Configuring a bean mapping looks like this: |
| <pre class="xml"><beanMapping qname="ns:local" xmlns:ns="someNamespace" |
| languageSpecificType="java:my.java.thingy"/></pre> |
| The <beanMapping> tag maps a Java class (presumably a bean) to an XML |
| QName. You'll note that it has two important attributes, <b>qname</b> and |
| <b>languageSpecificType</b>. |
| So in this case, we'd be mapping the "my.java.thingy" class to the XML |
| QName [someNamespace]:[local]. |
| <p>Let's take a look at how this works in practice. Go look at <a href="../samples/userguide/example5/BeanService.java">samples/userguide/example5/BeanService.java</a>. The key |
| thing to notice is that the argument to the service method is an Order |
| object. Since Order is not a basic type which Axis understands by default, |
| trying to run this service without a type mapping will result in a fault. |
| (If you want to try this for yourself, you can use the bad-deploy.wsdd |
| file in the example5 directory.) But if we put a beanMapping into our deployment, |
| all will be well. Here's how to run this example (from the example5 directory): |
| <pre class="example">% java org.apache.axis.client.AdminClient -llocal:///AdminService deploy.wsdd |
| <Admin>Done processing</Admin> |
| |
| % java samples.userguide.example5.Client -llocal:// |
| Hi, Glen Daniels! |
| |
| You seem to have ordered the following: |
| |
| 1 of item : mp3jukebox |
| 4 of item : 1600mahBattery |
| |
| If this had been a real order processing system, we'd probably have charged you about now. |
| % |
| |
| </pre> |
| |
| <h3> |
| When Beans Are Not Enough - Custom Serialization</h3> |
| Just as JWS deployment is sometimes not flexible enough to meet all needs, |
| the default bean serialization model isn't robust enough to handle every |
| case either. At times there will be non-bean Java classes (especially in |
| the case of pre-existing assets) which you need to map to/from XML, and |
| there also may be some custom XML schema types which you want to map into |
| Java in particular ways. Axis gives you the ability to write custom serializers/deserializers, |
| and some tools to help make your life easier when you do so. |
| <p><i><font color="#FF0000">TBD - this section will be expanded in a future |
| version! For now look at the DataSer/DataDeser |
| classes (in samples/encoding). |
| Also look at the BeanSerializer, BeanDeserializer, ArraySerializer, ArrayDeserializer and other classes in the org.apache.axis.encoding.ser package. |
| </font></i> |
| <h4> |
| Deploying custom mappings - the <typeMapping> tag</h4> |
| Now that you've built your serializers and deserializers, you need to tell |
| Axis which types they should be used for. You do this with a typeMapping |
| tag in WSDD, which looks like this: |
| <pre class="xml"><typeMapping qname="ns:local" xmlns:ns="someNamespace" |
| languageSpecificType="java:my.java.thingy" |
| serializer="my.java.Serializer" |
| deserializer="my.java.DeserializerFactory" |
| encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></pre> |
| <p>This looks a lot like the <beanMapping> tag we saw earlier, but there |
| are three extra attributes. One, <b>serializer</b>, is the Java class name |
| of the Serializer <i>factory</i> which gets the serializer to |
| be used to marshal an object of the specified Java class |
| (i.e., my.java.thingy) into XML. Another, <b>deserializer</b>, is |
| the class name of a Deserializer <i>factory</i> that gets the deserializer |
| to be used to unmarshall XML into the correct Java class. The final attribute, |
| the <b>encodingStyle</b>, which is SOAP encoding. |
| <p>(The <beanMapping> tag is really just shorthand for a <typeMapping> tag |
| with <tt>serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"</tt>, |
| <tt>deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"</tt>, |
| and <tt>encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"</tt>, but clearly it |
| can save a lot of typing!) |
| <h4>Deploying array mappings - the <arrayMapping> tag</h4> |
| Another variation around typeMapping is arrayMapping. The arrayMapping tag is useful |
| for advanced users wanting to exatly control how their arrays are serialized throught |
| the wire. |
| <pre class="xml"><arrayMapping qname="ns:ArrayOfthingy" xmlns:ns="someNamespaceURI" |
| languageSpecificType="java:my.java.array.thingy[]" |
| innerType="ns2:thingy" xmlns:ns2="anotherNamespaceURI" |
| encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></pre> |
| No need here to specify a serializer/deserializer couple, the arrayMapping tag |
| is only about arrays (no List, ...). The added attribute (<i>innerType</i>) is used |
| to tell Axis what precisely is the item type of the Array. |
| <h2> |
| <a NAME="WSDL"></a>Using WSDL with Axis</h2> |
| The <a href="http://www.w3.org/TR/wsdl">Web Service Description Language</a> |
| is a specification authored by IBM and Microsoft, and supported by many |
| other organizations. WSDL serves to describe Web Services in a structured |
| way. A WSDL description of a service tells us, in a machine-understandable |
| way, the interface to the service, the data types it uses, and where the |
| service is located. Please see the spec (follow the link in the first sentence) |
| for details about WSDL's format and options. |
| <p>Axis supports WSDL in three ways: |
| <ol> |
| <li> |
| When you deploy a service in Axis, users may then access your service's |
| URL with a standard web browser and by appending "?WSDL" to the end of |
| the URL, they will obtain an automatically-generated WSDL document which |
| describes your service.</li> |
| |
| <li> |
| We provide a "WSDL2Java" tool which will build Java proxies and skeletons |
| for services with WSDL descriptions.</li> |
| |
| <li> |
| We provide a "Java2WSDL" tool which will build WSDL from Java classes.</li> |
| </ol> |
| |
| <h3> |
| <a NAME="WSDL: Obtaining WSDL for deployed services"></a>?WSDL: Obtaining |
| WSDL for deployed services</h3> |
| When you make a service available using Axis, there is typically a unique |
| URL associated with that service. For JWS files, that URL is simply the |
| path to the JWS file itself. For non-JWS services, this is usually the |
| URL "http://<host>/axis/services/<service-name>". |
| <p>If you access the service URL in a browser, you'll see a message indicating |
| that the endpoint is an Axis service, and that you should usually access |
| it using SOAP. However, if you tack on "?wsdl" to the end of the URL, Axis |
| will automatically generate a service description for the deployed service, |
| and return it as XML in your browser (try it!). The resulting description |
| may be saved or used as input to proxy-generation, described next. You |
| can give the WSDL-generation URL to your online partners, and they'll be |
| able to use it to access your service with toolkits like .NET, SOAP::Lite, |
| or any other software which supports using WSDL. |
| <p>You can also generate WSDL files from existing Java classes (see <a href="#Java2WSDL: Building WSDL from Java">Java2WSDL: |
| Building WSDL from Java</a> ). |
| <br> |
| <h3><a NAME="WSDL2Java: Building stubs, skeletons, and data"></a>WSDL2Java: |
| Building stubs, skeletons, and data types from WSDL</h3> |
| |
| <h4>Client-side bindings</h4> |
| <p>You'll find the Axis WSDL-to-Java tool in "org.apache.axis.wsdl.WSDL2Java". |
| The basic invocation form looks like this:</p> |
| <pre class="example"> |
| % java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL) |
| </pre> |
| |
| <p>This will generate only those bindings necessary for the client. |
| Axis follows the JAX-RPC specification when generating Java client bindings |
| from WSDL. For this discussion, assume we executed the following:</p> |
| <pre class="example"> |
| % cd samples/addr |
| % java org.apache.axis.wsdl.WSDL2Java AddressBook.wsdl |
| </pre> |
| <p>The generated files will reside in the directory "AddressFetcher2". |
| They are put here because that is the target namespace from the WSDL and namespaces map to Java packages. |
| Namespaces will be discussed in detail later.</p> |
| <table BORDER COLS=2 WIDTH="100%" > |
| <tr> |
| <td><b>WSDL clause</b></td> |
| |
| <td><b>Java class(es) generated</b></td> |
| </tr> |
| |
| <tr> |
| <td>For each entry in the type section</td> |
| |
| <td>A java class</td> |
| </tr> |
| |
| <tr> |
| <td></td> |
| |
| <td>A holder if this type is used as an inout/out parameter</td> |
| </tr> |
| |
| <tr> |
| <td>For each portType</td> |
| |
| <td>A java interface</td> |
| </tr> |
| |
| <tr> |
| <td>For each binding</td> |
| |
| <td>A stub class</td> |
| </tr> |
| |
| <tr> |
| <td>For each service</td> |
| |
| <td>A service interface</td> |
| </tr> |
| |
| <tr> |
| <td></td> |
| |
| <td>A service implementation (the locator)</td> |
| </tr> |
| </table> |
| |
| There is an <a href="ant/axis-wsdl2java.html">Ant Task</a> to integrate this |
| action with an Ant based build process. |
| |
| <h4>Types</h4> |
| <p>The Java class generated from a WSDL type will be named from the WSDL type. |
| This class will typically, though not always, be a bean. For example, |
| given the WSDL (the WSDL used throughout the WSDL2Java discussion is from |
| the <a href="../samples/addr/AddressBook.wsdl">Address Book sample</a>):</p> |
| <pre class="example"> |
| <xsd:complexType name="phone"> |
| <xsd:all> |
| <xsd:element name="areaCode" type="xsd:int"/> |
| <xsd:element name="exchange" type="xsd:string"/> |
| <xsd:element name="number" type="xsd:string"/> |
| </xsd:all> |
| </xsd:complexType> |
| </pre> |
| <p>WSDL2Java will generate: |
| <pre class="example"> |
| public class Phone implements java.io.Serializable { |
| public Phone() {...} |
| public int getAreaCode() {...} |
| public void setAreaCode(int areaCode) {...} |
| public java.lang.String getExchange() {...} |
| public void setExchange(java.lang.String exchange) {...} |
| public java.lang.String getNumber() {...} |
| public void setNumber(java.lang.String number) {...} |
| public boolean equals(Object obj) {...} |
| public int hashCode() {...} |
| } |
| </pre> |
| <h4>Mapping XML to Java types : Metadata</h4> |
| <p>Notice in the mapping above, the XML type name is "phone" and the |
| generated Java class is "Phone" - the capitalization of the first |
| letter has changed to match the Java coding convention that classes begin with |
| an uppercase letter. This sort of thing happens a lot, because the rules for |
| expressing XML names/identifiers are much less restrictive than those for Java. |
| For example, if one of the sub-elements in the "phone" type above |
| was named "new", we couldn't just generate a Java field called "new", |
| since that is a reserved word and the resultant source code would fail to compile.</p> |
| <p>To support this kind of mapping, and also to enable the serialization/deserialization |
| of XML attributes, we have a <b>type metadata</b> system which allows us to |
| associate Java data classes with descriptors which control these things.</p> |
| <p>When the WSDL2Java tool creates a data bean like the Phone class above, it |
| notices if the schema contains any attributes, or any names which do not map |
| directly to Java field/property names. If it finds any of these things, it will |
| generate a static piece of code to supply a <b>type descriptor</b> for the class. |
| The type descriptor is essentially a collection of <b>field descriptors</b>, |
| each of which maps a Java field/property to an XML element or attribute.</p> |
| <p>To see an example of this kind of metadata, look at the "test.encoding.AttributeBean" |
| class in the Axis source, or generate your own bean from XML which uses attributes |
| or names which would be illegal in Java.</p> |
| <h4>Holders</h4> |
| <p>This type may be used as an inout or out parameter. Java does not |
| have the concept of inout/out parameters. In order to achieve this |
| behavior, JAX-RPC specifies the use of holder classes. A holder class |
| is simply a class that contains an instance of its type. For example, |
| the holder for the Phone class would be:</p> |
| <pre class="example"> |
| package samples.addr.holders; |
| public final class PhoneHolder implements javax.xml.rpc.holders.Holder { |
| public samples.addr.Phone value; |
| |
| public PhoneHolder() |
| { |
| } |
| |
| public PhoneHolder(samples.addr.Phone value) { |
| this.value = value; |
| } |
| } |
| </pre> |
| <p>A holder class is <b>only</b> generated for a type if that type is used as |
| an inout or out parameter. Note that the holder class has the suffix "Holder" |
| appended to the class name, and it is generated in a sub-package with the "holders". </p> |
| <p>The holder classes for the primitive types can be found in javax.xml.rpc.holders.</p> |
| <h4>PortTypes</h4> |
| <p>The Service Definition Interface (SDI) is the interface that's derived |
| from a WSDL's portType. This is the interface you use to access the |
| operations on the service. For example, given the WSDL:</p> |
| <pre class="example"> |
| <message name="empty"> |
| <message name="AddEntryRequest"> |
| <part name="name" type="xsd:string"/> |
| <part name="address" type="typens:address"/> |
| </message> |
| <portType name="AddressBook"> |
| <operation name="addEntry"> |
| <input message="tns:AddEntryRequest"/> |
| <output message="tns:empty"/> |
| </operation> |
| </portType> |
| </pre> |
| <p>WSDL2Java will generate: |
| <pre class="example"> |
| public interface AddressBook extends java.rmi.Remote { |
| public void addEntry(String name, Address address) throws java.rmi.RemoteException; |
| } |
| </pre> |
| |
| <p>A note about the name of the SDI. The name of the SDI is typically the |
| name of the portType. However, to construct the SDI, WSDL2Java needs |
| information from both the portType <b>and</b> the binding. |
| (This is unfortunate and is a topic of discussion for WSDL version 2.) |
| |
| |
| <p>JAX-RPC says (section 4.3.3): "The name of the Java interface is mapped |
| from the name attribute of the wsdl:portType element. ... If the mapping to |
| a service definition interface uses elements of the wsdl:binding ..., then |
| the name of the service definition interface is mapped from the name of the |
| wsdl:binding element." |
| <p>Note the name of the spec. It contains the string "RPC". So this spec, |
| and WSDL2Java, assumes that the interface generated from the portType is an |
| RPC interface. If information from the binding tells us otherwise (in |
| other words, we use elements of the wsdl:binding), then the name of the |
| interface is derived instead from the binding. |
| <p>Why? We could have one portType - pt - and two bindings - bRPC and |
| bDoc. Since document/literal changes what the interface looks like, we |
| cannot use a single interface for both of these bindings, so we end up with |
| two interfaces - one named pt and another named bDoc - and two stubs - |
| bRPCStub (which implements pt) and bDocStub (which implements bDoc). |
| <p>Ugly, isn't it? But you can see why it's necessary. Since |
| document/literal changes what the interface looks like, and we could |
| have more than one binding referring to a single portType, we have to |
| create more than one interface, and each interface must have a unique name. |
| |
| <h4> |
| Bindings</h4> |
| |
| A Stub class implements the SDI. Its name is the binding name with |
| the suffix "Stub". It contains the code which turns the method invocations |
| into SOAP calls using the Axis Service and Call objects. It stands |
| in as a <b>proxy</b> (another term for the same idea) for the remote service, |
| letting you call it exactly as if it were a local object. In other words, |
| you don't need to deal with the endpoint URL, namespace, or parameter arrays |
| which are involved in dynamic invocation via the Service and Call objects. |
| The stub hides all that work for you. |
| <p>Given the following WSDL snippet: |
| <pre class="example"><binding name="AddressBookSOAPBinding" type="tns:AddressBook"> |
| ... |
| </binding></pre> |
| <p>WSDL2Java will generate: |
| <pre class="example">public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub |
| implements AddressBook { |
| public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault |
| {...} |
| |
| public AddressBookSOAPBindingStub(URL endpointURL, |
| javax.xml.rpc.Service service) |
| throws org.apache.axis.AxisFault |
| {...} |
| <br> public AddressBookSOAPBindingStub(javax.xml.rpc.Service service) |
| throws org.apache.axis.AxisFault |
| {...} |
| <br> public void addEntry(String name, Address address) throws RemoteException |
| {...}<br>}</pre> |
| <h4> |
| Services</h4> |
| Normally, a client program would not instantiate a stub directly. |
| It would instead instantiate a service locator and call a get method which |
| returns a stub. This locator is derived from the service clause in |
| the WSDL. WSDL2Java generates two objects from a service clause. |
| For example, given the WSDL: |
| <pre class="example"><service name="AddressBookService"> |
| <port name="AddressBook" binding="tns:AddressBookSOAPBinding"> |
| <soap:address location="http://localhost:8080/axis/services/AddressBook"/> |
| </port> |
| </service></pre> |
| <p>WSDL2Java will generate the service interface: |
| <pre class="example">public interface AddressBookService extends javax.xml.rpc.Service { |
| public String getAddressBookAddress(); |
| <br> public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException; |
| <br> public AddressBook getAddressBook(URL portAddress) throws javax.xml.rpc.ServiceException; |
| }</pre> |
| <p>WSDL2Java will also generate the locator which implements this interface: |
| <pre class="example">public class AddressBookServiceLocator extends org.apache.axis.client.Service |
| implements AddressBookService { |
| ... |
| }</pre> |
| <p>The service interface defines a get method for each port listed in the |
| service element of the WSDL. The locator is the implementation of this |
| service interface. It implements these get methods. It serves as |
| a locator for obtaining Stub instances. The Service class will by default |
| make a Stub which points to the endpoint URL described in the WSDL file, |
| but you may also specify a different URL when you ask for the PortType. |
| <p>A typical usage of the stub classes would be as follows: |
| |
| <pre class="example">public class Tester |
| { |
| public static void main(String [] args) throws Exception { |
| // Make a service |
| AddressBookService service = new AddressBookServiceLocator(); |
| |
| // Now use the service to get a stub which implements the SDI. |
| AddressBook port = service.getAddressBook(); |
| |
| // Make the actual call |
| Address address = new Address(...); |
| port.addEntry("Russell Butek", address); |
| }<br>}</pre> |
| |
| <h4> |
| Server-side bindings</h4> |
| Just as a stub is the client side of a Web Service represented in Java, |
| a <b>skeleton</b> is a Java framework for the server side. To make |
| skeleton classes, you just specify the "--server-side --skeletonDeploy true" options |
| to WSDL2Java. |
| For instance, using the AddressBook.wsdl as we had above: |
| <pre class="example">% java org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true AddressBook.wsdl</pre> |
| <p>You will see that WSDL2Java generates all the classes that were generated |
| before for the client, but it generates a few new files: |
| <br> |
| <br> |
| <table BORDER COLS=2 WIDTH="100%" > |
| <tr> |
| <td><b>WSDL clause</b></td> |
| |
| <td><b>Java class(es) generated</b></td> |
| </tr> |
| |
| <tr> |
| <td>For each binding</td> |
| |
| <td>A skeleton class</td> |
| </tr> |
| |
| <tr> |
| <td></td> |
| |
| <td>An implementation template class</td> |
| </tr> |
| |
| <tr> |
| <td>For all services</td> |
| |
| <td>One deploy.wsdd file</td> |
| </tr> |
| |
| <tr> |
| <td></td> |
| |
| <td>One undeploy.wsdd file</td> |
| </tr> |
| </table> |
| |
| <p>If you don't specify the "--skeletonDeploy true" option, a skeleton will not be |
| generated. Instead, the generated deploy.wsdd will indicate that the implementation |
| class is deployed directly. In such cases, the deploy.wsdd contains extra meta |
| data describing the operations and parameters of the implementation class. |
| |
| Here is how you run WSDL2Java to deploy directly to the implementation: |
| <pre class="example">% java org.apache.axis.wsdl.WSDL2Java --server-side AddressBook.wsdl</pre> |
| <p>And here are the server side files that are generated: |
| <br> |
| <br> |
| <table BORDER COLS=2 WIDTH="100%" > |
| <tr> |
| <td><b>WSDL clause</b></td> |
| |
| <td><b>Java class(es) generated</b></td> |
| </tr> |
| |
| <tr> |
| <td>For each binding</td> |
| <td>An implementation template class</td> |
| |
| </tr> |
| |
| <tr> |
| <td>For all services</td> |
| |
| <td>One deploy.wsdd file with operation meta data</td> |
| </tr> |
| |
| <tr> |
| <td></td> |
| |
| <td>One undeploy.wsdd file</td> |
| </tr> |
| </table> |
| |
| <h4> |
| Bindings</h4> |
| <h5> |
| Skeleton Description (for Skeleton Deployment) </h5> |
| The skeleton class is the class that sits between the Axis engine and the |
| actual service implementation. Its name is the binding name with |
| suffix "Skeleton". For example, for the AddressBook binding, WSDL2Java |
| will generate: |
| <pre class="example">public class AddressBookSOAPBindingSkeleton implements AddressBook, |
| org.apache.axis.wsdl.Skeleton { |
| private AddressBook impl; |
| |
| public AddressBookSOAPBindingSkeleton() { |
| this.impl = new AddressBookSOAPBindingImpl(); |
| } |
| |
| public AddressBookSOAPBindingSkeleton(AddressBook impl) { |
| this.impl = impl; |
| } |
| |
| public void addEntry(java.lang.String name, Address address) |
| throws java.rmi.RemoteException |
| { |
| impl.addEntry(name, address); |
| } |
| }</pre> |
| <p>(The real skeleton is actually much richer. For brevity we just show |
| you the basic skeleton.) |
| <p>The skeleton contains an implementation of the AddressBook service. |
| This implementation is either passed into the skeleton on construction, |
| or an instance of the generated implementation is created. When the |
| Axis engine calls the skeleton's addEntry method, it simply delegates the |
| invocation to the real implementation's addEntry method. |
| <h5> |
| Implementation Template Description </h5> |
| <p>WSDL2Java also generates an implementation template |
| from the binding: |
| <pre class="example">public class AddressBookSOAPBindingImpl implements AddressBook { |
| <br> public void addEntry(String name, Address address) |
| throws java.rmi.RemoteException { |
| } |
| }</pre> |
| <p>This template could actually be used as a test implementation but, as |
| you can see, it doesn't do anything. It is intended that the service |
| writer fill out the implementation from this template.</p> |
| <p>When WSDL2Java is asked to generate the implementation template (via the --server-side |
| flag), it will ONLY generate it if it does not already exist. If this |
| implementation already exists, it will not be overwritten.</p> |
| <h4>Services</h4> |
| <p>The tool also builds you a "deploy.wsdd" and an "undeploy.wsdd" for each |
| service for use with the AdminClient. These files may be used to deploy |
| the service once you've filled in the methods of the Implementation class, |
| compiled the code, and made the classes available to your Axis engine.</p> |
| <h3><a NAME="Java2WSDL: Building WSDL from Java"></a>Java2WSDL: Building WSDL |
| from Java</h3> |
| The Java2WSDL and WSDL2Java emitters make it easy to develop a new web service. |
| The following sections describe the steps in building a web service from a Java interface. |
| <br> |
| <h4> |
| Step 1: Provide a Java interface or class</h4> |
| Write and compile a Java interface (or class) that describes the web service |
| interface. Here is an example interface that describes a web services |
| that can be used to set/query the price of widgets |
| (<a href="../samples/userguide/example6/WidgetPrice.java">samples/userguide/example6/WidgetPrice.java</a>): |
| <pre class="example">package samples.userguide.example6; |
| |
| /** |
| * Interface describing a web service to set and get Widget prices. |
| **/ |
| public interface WidgetPrice { |
| public void setWidgetPrice(String widgetName, String price); |
| public String getWidgetPrice(String widgetName); |
| }</pre> |
| <p><b>Note: </b>If you compile your class with debug information, Java2WSDL |
| will use the debug information to obtain the method parameter names. |
| <h4> |
| Step 2: Create WSDL using Java2WSDL</h4> |
| Use the Java2WSDL tool to create a WSDL file from the interface above. |
| <p>Here is an example invocation that produces the wsdl file (<tt>wp.wsdl</tt>) |
| from the interface described in the previous section (entered all on one line): |
| <pre class="example">% java org.apache.axis.wsdl.Java2WSDL -o wp.wsdl |
| -l"http://localhost:8080/axis/services/WidgetPrice" -n "urn:Example6" |
| -p"samples.userguide.example6" "urn:Example6" samples.userguide.example6.WidgetPrice</pre> |
| <p>Where: |
| <ul> |
| <li> |
| -o indicates the name of the <b><i>output WSDL</i></b> file</li> |
| |
| <li> |
| -l indicates the<b><i> location of the service</i></b></li> |
| |
| <li> |
| -n is the target <b><i>namespace</i></b> of the WSDL file</li> |
| |
| <li> |
| -p indicates a mapping from the <b><i>package to a namespace</i></b>. |
| There may be multiple mappings.</li> |
| |
| <li> |
| the class specified contains the interface of the webservice.</li> |
| </ul> |
| The output WSDL document will contain the appropriate WSDL types, messages, |
| portType, bindings and service descriptions to support a SOAP rpc, encoding |
| web service. If your specified interface methods reference other |
| classes, the Java2WSDL tool will generate the appropriate xml types to |
| represent the classes and any nested/inherited types. The tool supports |
| JAX-RPC complex types (bean classes), extension classes, enumeration classes, |
| arrays and Holder classes. |
| <p>The Java2WSDL tool has many additional options which are detailed in the <a href="reference.html#Java2WSDL">reference |
| guide</a>. |
| |
| There is an <a href="ant/axis-java2wsdl.html">Ant Task</a> to integrate this |
| action with an Ant based build process. |
| |
| <h4> |
| Step 3: Create Bindings using WSDL2Java</h4> |
| |
| Use the generated WSDL file to build the appropriate client/server bindings |
| for the web service (see <a href="#WSDL2Java: Building stubs, skeletons, and data">WSDL2Java</a>): |
| <pre class="example">% java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true -Nurn:Example6 samples.userguide.example6 wp.wsdl</pre> |
| <p>This will generate the following files: |
| <ul> |
| <li> <b><tt>WidgetPriceSoapBindingImpl.java</tt></b> : Java file containing |
| the default server implementation of the WidgetPrice web service.</li> |
| <br> |
| You will need to modify the *SoapBindingImpl file to add your implementation |
| (see <a href="../samples/userguide/example6/WidgetPriceSoapBindingImpl.java">../samples/userguide/example6/WidgetPriceSoapBindingImpl.java</a> |
| ). |
| <li> <b><tt>WidgetPrice.java</tt></b>: New interface file that contains |
| the appropriate <b><tt>java.rmi.Remote</tt></b> usages.</li> |
| <li> <b><tt>WidgetPriceService.java</tt></b>: Java file containing the client |
| side service interface.</li> |
| <li> <b><tt>WidgetPriceServiceLocator.java</tt></b>: Java file containing the |
| client side service implementation class.</li> |
| <li> <b><tt>WidgetPriceSoapBindingSkeleton.java</tt></b>: Server side skeleton.</li> |
| <li> <b><tt>WidgetPriceSoapBindingStub.java</tt></b>: Client side stub.</li> |
| <li> <b><tt>deploy.wsdd</tt></b>: Deployment descriptor</li> |
| <li> <b><tt>undeploy.wsdd</tt></b>: Undeployment descriptor</li> |
| <li> (data types): Java files will be produced for all of the other types |
| and holders necessary for the web service. There are no additional files |
| for the WidgetPrice web service.</li> |
| </ul> |
| <p>Now you have all of the necessary files to build your client/server side code |
| and deploy the web service!</p> |
| <h2> |
| <a NAME="published interfaces"></a>Published Axis Interfaces</h2> |
| |
| Although you may use any of the interfaces and classes present in Axis, you need to |
| be aware that some are more stable than others since there is a continuing |
| need to refactor Axis to maintain and improve its modularity. |
| <p>Hence certain interfaces are designated as <i>published</i>, which means |
| that they are relatively stable. As Axis is refactored, the Axis developers |
| will try to avoid changing published interfaces unnecessarily and will |
| certainly consider the impact on users of any modifications. |
| <p>So if you stick to using only published interfaces, you'll minimise |
| the pain of migrating between releases of Axis. On the other hand, if you |
| decide to use unpublished interfaces, migrating between releases could |
| be an interesting exercise! If you would like an interface to be published, |
| you should make the case for this on the |
| <a href="mailto:axis-user@ws.apache.org">axis-user</a> |
| mailing list. |
| <p>The current list of published interfaces is as follows: |
| <ul> |
| <li> |
| JAX-RPC interfaces. |
| These interfaces are from JAX-RPC 1.0 specification, and will change only when |
| new versions of the specification are released. |
| <ul> |
| <li>javax.xml.messaging.Endpoint</li> |
| <li>javax.xml.messaging.URLEndpoint</li> |
| <li>javax.xml.rpc.Call</li> |
| <li>javax.xml.rpc.FaultException</li> |
| <li>javax.xml.rpc.JAXRPCException</li> |
| <li>javax.xml.rpc.ParameterMode</li> |
| <li>javax.xml.rpc.Service</li> |
| <li>javax.xml.rpc.ServiceException</li> |
| <li>javax.xml.rpc.ServiceFactory</li> |
| <li>javax.xml.rpc.Stub</li> |
| <li>javax.xml.rpc.encoding.DeserializationContext</li> |
| <li>javax.xml.rpc.encoding.Deserializer</li> |
| <li>javax.xml.rpc.encoding.DeserializerFactory</li> |
| <li>javax.xml.rpc.encoding.SerializationContext</li> |
| <li>javax.xml.rpc.encoding.Serializer</li> |
| <li>javax.xml.rpc.encoding.SerializerFactory</li> |
| <li>javax.xml.rpc.encoding.TypeMapping</li> |
| <li>javax.xml.rpc.encoding.TypeMappingRegistry</li> |
| <li>javax.xml.rpc.handler.Handler</li> |
| <li>javax.xml.rpc.handler.HandlerChain</li> |
| <li>javax.xml.rpc.handler.HandlerInfo</li> |
| <li>javax.xml.rpc.handler.HandlerRegistry</li> |
| <li>javax.xml.rpc.handler.MessageContext</li> |
| <li>javax.xml.rpc.handler.soap.SOAPMessageContext</li> |
| <li>javax.xml.rpc.holders.BigDecimalHolder</li> |
| <li>javax.xml.rpc.holders.BigIntegerHolder</li> |
| <li>javax.xml.rpc.holders.BooleanHolder</li> |
| <li>javax.xml.rpc.holders.BooleanWrapperHolder</li> |
| <li>javax.xml.rpc.holders.ByteArrayHolder</li> |
| <li>javax.xml.rpc.holders.ByteHolder</li> |
| <li>javax.xml.rpc.holders.ByteWrapperArrayHolder</li> |
| <li>javax.xml.rpc.holders.ByteWrapperHolder</li> |
| <li>javax.xml.rpc.holders.CalendarHolder</li> |
| <li>javax.xml.rpc.holders.DateHolder</li> |
| <li>javax.xml.rpc.holders.DoubleHolder</li> |
| <li>javax.xml.rpc.holders.DoubleWrapperHolder</li> |
| <li>javax.xml.rpc.holders.FloatHolder</li> |
| <li>javax.xml.rpc.holders.FloatWrapperHolder</li> |
| <li>javax.xml.rpc.holders.Holder</li> |
| <li>javax.xml.rpc.holders.IntHolder</li> |
| <li>javax.xml.rpc.holders.IntegerWrapperHolder</li> |
| <li>javax.xml.rpc.holders.LongHolder</li> |
| <li>javax.xml.rpc.holders.LongWrapperHolder</li> |
| <li>javax.xml.rpc.holders.ObjectHolder</li> |
| <li>javax.xml.rpc.holders.QNameHolder</li> |
| <li>javax.xml.rpc.holders.ShortHolder</li> |
| <li>javax.xml.rpc.holders.ShortWrapperHolder</li> |
| <li>javax.xml.rpc.holders.StringHolder</li> |
| <li>javax.xml.rpc.namespace.QName</li> |
| <li>javax.xml.rpc.server.ServiceLifecycle</li> |
| <li>javax.xml.rpc.soap.SOAPFault</li> |
| <li>javax.xml.rpc.soap.SOAPHeaderFault</li> |
| <li>javax.xml.transform.Source</li> |
| </ul> |
| </li> |
| <li>Axis interfaces. These have less guarantees of stability: |
| <ul> |
| <li>org.apache.axis.AxisFault</li> |
| <li>org.apache.axis.Handler</li> |
| <li>org.apache.axis.DefaultEngineConfigurationFactory</li> |
| <li>org.apache.axis.EngineConfiguration</li> |
| <li>org.apache.axis.EngineConfigurationFactory</li> |
| <li>org.apache.axis.Message</li> |
| <li>org.apache.axis.MessageContext</li> |
| <li>org.apache.axis.SOAPPart</li> |
| <li>org.apache.axis.client.Call</li> |
| <li>org.apache.axis.client.Service</li> |
| <li>org.apache.axis.client.ServiceFactory</li> |
| <li>org.apache.axis.client.Stub</li> |
| <li>org.apache.axis.client.Transport</li> |
| <li>org.apache.axis.description.TypeDesc</li> |
| <li>org.apache.axis.description.AttributeDesc</li> |
| <li>org.apache.aixs.description.ElementDesc</li> |
| <li>org.apache.axis.encoding.DeserializationContext</li> |
| <li>org.apache.axis.encoding.Deserializer</li> |
| <li>org.apache.axis.encoding.DeserializerFactory</li> |
| <li>org.apache.axis.encoding.DeserializerTarget</li> |
| <li>org.apache.axis.encoding.FieldTarget</li> |
| <li>org.apache.axis.encoding.MethodTarget</li> |
| <li>org.apache.axis.encoding.SerializationContext</li> |
| <li>org.apache.axis.encoding.Serializer</li> |
| <li>org.apache.axis.encoding.SerializerFactory</li> |
| <li>org.apache.axis.encoding.SimpleType</li> |
| <li>org.apache.axis.encoding.Target</li> |
| <li>org.apache.axis.encoding.TypeMapping</li> |
| <li>org.apache.axis.encoding.TypeMappingRegistry</li> |
| <li>org.apache.axis.encoding.ser.BaseDeserializerFactory</li> |
| <li>org.apache.axis.encoding.ser.BaseSerializerFactory</li> |
| <li>org.apache.axis.encoding.ser.BeanPropertyTarget</li> |
| <li>org.apache.axis.encoding.ser.SimpleSerializer</li> |
| <li>org.apache.axis.encoding.ser.SimpleDeserializer</li> |
| <li>org.apache.axis.session.Session</li> |
| <li>org.apache.axis.transport.http.SimpleAxisServer</li> |
| <li>org.apache.axis.transport.jms.SimpleJMSListener</li> |
| <li>org.apache.axis.utils.BeanProperty</li> |
| <li>org.apache.axis.wsdl.WSDL2Java</li> |
| <li>org.apache.axis.wsdl.Java2WSDL</li> |
| </ul> |
| </ul> |
| <h2><a name="newbie"></a>Newbie Tips: Finding Your Way Around</h2> |
| <p>So you've skimmed the User's Guide and written your first .jws service, |
| and everything went perfectly! Now it's time to get to work on a real project, |
| and you have something specific you need to do that the User's Guide didn't |
| cover. |
| It's a simple thing, and you know it must be in Axis <em>somewhere</em>, but |
| you don't know what it's called or how to get at it. This section is meant to |
| give you some starting points for your search.</p> |
| <h3>Places to Look for Clues</h3> |
| <p>Here are the big categories.</p> |
| <ul> |
| <li><a href="../samples/"><b>The samples.</b></a> These examples are |
| complete with deployment descriptors and often contain both client and |
| server code. |
| </li> |
| <li><b>The Javadocs.</b> Full Javadocs are included with the binary |
| distribution. |
| The Javadocs can be intimidating at first, but once you know the major user |
| classes, they are one of the fastest ways to an answer.</li> |
| <li><b><a href="http://ws.apache.org/axis/mail.html">The mailing list |
| archives.</a></b> |
| If you know what you want but don't know what it's called in Axis, this is |
| the best place to look. Chances are someone has wanted the same thing and |
| someone else has used (or developed) Axis long enough know the name.</li> |
| |
| <li> Consult the <A HREF="http://ws.apache.org/axis">Axis web site</a> for updated documentation and the |
| <a href="http://nagoya.apache.org/wiki/apachewiki.cgi?AxisProjectPages">Axis Wiki</a> |
| for its Frequently Asked Questions (FAQ), installation notes, |
| interoperability issues lists, and other useful information. |
| </li> |
| |
| <li> <b>WSDL2Java.</b> Point WSDL2Java at a known webservice that does some |
| of the things you want to do. See what comes out. This is useful even if |
| you |
| will be writing the actual service or client from scratch. If you want |
| nice, |
| human-readable descriptions of existing web services, try |
| <a href="http://www.xmethods.net">http://www.xmethods.net</a>.</li> |
| </ul> |
| <h3>Classes to Know</h3> |
| <h4>org.apache.axis.MessageContext</h4> |
| <p>The answer to most "where do I find..." questions for an Axis web |
| service is "in the MessageContext." Essentially everything Axis |
| knows |
| about a given request/response can be retrieved via the MessageContext. Here |
| Axis stores:</p> |
| <ul> |
| <li>A reference to the AxisEngine</li> |
| <li>The request and response messages (<code>org.apache.axis.Message</code> |
| objects available via getter and setter methods)</li> |
| <li>Information about statefulness and service scope (whether the service is |
| maintaining session information, etc.)</li> |
| <li>The current status of processing (whether or not the "pivot" |
| has |
| been passed, which determines whether the request or response is the |
| current |
| message)</li> |
| <li>Authentication information (username and password, which can be provided |
| by a servlet container or other means)</li> |
| <li>Properties galore. Almost anything you would want to know about the |
| message |
| can be retrieved via <code>MessageContext.getProperty()</code>. |
| You only need |
| to know the name of the property. This can be tricky, but it is usually a |
| constant, like those defined in |
| <code>org.apache.axis.transport.http.HTTPConstants</code>. |
| So, for example, to retrieve the ServletContext for the Axis Servlet, you |
| would want: <code>((HttpServlet)msgC.getProperty(HTTPConstants.MC_HTTP_SERVLET)).getServletContext();</code><br> |
| </li> |
| </ul> |
| <p>From within your service, the current MessageContext object is always |
| available |
| via the static method <code>MessageContext.getCurrentContext()</code>. This |
| allows you to do any needed customization of the request and response |
| methods, |
| even from within an RPC service that has no explicit reference to the |
| MessageContext.</p> |
| <h4>org.apache.axis.Message</h4> |
| <p>An <code>org.apache.axis.Message</code> object is Axis's representation of |
| a SOAP message. The request and response messages can be retrieved from the |
| MessageContext as described above. A Message has:</p> |
| <ul> |
| <li>MIME headers (if the message itself has MIME information)</li> |
| <li>Attachments (if the message itself has attachments)</li> |
| <li>A SOAPPart (and a convenience method for quick retrieval of the |
| SOAPPart's |
| SOAPEnvelope). The SOAPPart gives you access to the SOAP "guts" |
| of the message (everything inside the <soap:Envelope> tags)</li> |
| </ul> |
| <h4>org.apache.axis.SOAPEnvelope</h4> |
| <p>As you can see, starting with the MessageContext lets you work your way |
| down |
| through the API, discovering all the information available to you about a |
| single |
| request/response exchange. A MessageContext has two Messages, which each |
| have |
| a SOAPPart that contains a SOAPEnvelope. The SOAPEnvelope, in turn, holds |
| a full representation of the SOAP Envelope that is sent over the wire. From |
| here you can get and set the contents of the SOAP Header and the SOAP Body. |
| See the Javadocs for a full list of the properties available.</p> |
| <h2> <a NAME="tcpmon"></a>Appendix : Using the Axis TCP Monitor (tcpmon)</h2> |
| The included "tcpmon" utility can be found in the org.apache.axis.utils |
| package. To run it from the command line: |
| <pre>% java org.apache.axis.utils.tcpmon [listenPort targetHost targetPort]</pre> |
| Without any of the optional arguments, you will get a gui which looks like |
| this: |
| <center> |
| <p><img SRC="images/tcpmon1.jpg" height=599 width=599></center> |
| |
| <p>To use the program, you should select a local port which tcpmon will |
| monitor for incoming connections, a target host where it will forward such |
| connections, and the port number on the target machine which should be |
| "tunneled" to. Then click "add". You should then notice another tab appearing |
| in the window for your new tunneled connection. Looking at that panel, |
| you'll see something like this: |
| <center> |
| <p><img SRC="images/tcpmon2.jpg" height=600 width=599></center> |
| |
| <p>Now each time a SOAP connection is made to the local port, you will |
| see the request appear in the "Request" panel, and the response from the |
| server in the "Response" panel. Tcpmon keeps a log of all request/response |
| pairs, and allows you to view any particular pair by selecting an entry |
| in the top panel. You may also remove selected entries, or all of them, |
| or choose to save to a file for later viewing. |
| <p>The "resend" button will resend the request you are currently viewing, and |
| record a new response. This is particularly handy in that you can edit the XML |
| in the request window before resending - so you can use this as a great tool |
| for testing the effects of different XML on SOAP servers. Note that you may |
| need to change the content-length HTTP header value before resending an edited |
| request. |
| |
| <h2> <a NAME="soapmon"></a>Appendix: Using the SOAP Monitor </h2> |
| Web service developers often have the need to see the SOAP messages |
| being used to invoke web services along with the results of those |
| messages. The goal of the SOAP Monitor utility is to provide |
| a way for these developers to monitor the SOAP messages being used |
| without requiring any special configuration or restarting of the |
| server. |
| <p> |
| In this utility, a handler has been written and added to the global |
| handler chain. As SOAP requests and responses are received, the SOAP |
| message information is forwarded to a SOAP monitor service where it |
| can be displayed using a web browser interface. |
| <p> |
| The SOAP message information is accessed with a web browser by going |
| to http://localhost:<port>/axis/SOAPMonitor (where |
| <port> is the port number where the application server is |
| running). |
| <p> |
| The SOAP message information is displayed through a web browser |
| by using an applet that opens a socket connection to the SOAP |
| monitor service. This applet requires a Java plug-in 1.3 or |
| higher to be installed in your browser. If you do not have a |
| correct plug-in, the browser should prompt you to install one. |
| <p> |
| The port used by the SOAP monitor service to comminicate with |
| applets is configurable. Edit the web.xml file for the Axis |
| web application to change the port to be used. |
| |
| <b>Note: The SOAP Monitor is NOT enabled by default for security reasons.</b> |
| To enable it, read <a href="install.html#soapmon">Enabling the |
| SOAP Monitor</a> in the Installation instructions. |
| |
| <a NAME="Glossary"> |
| <h2>Glossary</h2></a> |
| |
| <dl> |
| <dt> <i>Handler</i></dt> |
| <dd> A reusable class which is responsible for processing a MessageContext in |
| some custom way. The Axis engine invokes a series of Handlers whenever a request |
| comes in from a client or a transport listener.</dd> |
| <dt> <i>SOAP</i></dt> |
| <dd> The Simple Object Access Protocol (yes, despite the fact that it sometimes |
| doesn't seem so simple, and doesn't have anything to do with objects... :)). |
| You can read the SOAP 1.1 specification at <a href="http://www.w3.org/TR/SOAP">http://www.w3.org/TR/SOAP</a>. |
| The W3C is currently in the midst of work on SOAP 1.2, under the auspices |
| of the <a href="http://www.w3.org/2000/xp/Group/">XML Protocol Group</a>.</dd> |
| <dt> <i>Provider</i></dt> |
| <dd> A provider is the "back-end" Handler which is responsible for |
| actually performing the "meat" of the desired SOAP operation. Typically |
| this means calling a method on some back-end service object. The two commonly |
| used providers are RPCProvider and MsgProvider, both in the org.apache.axis.providers.java |
| package.</dd> |
| |
| </dl> |
| |
| </body> |
| </html> |