Apache | WS |
The Apache Axis ProjectAxisWebServices - AxisWebServices - Axis - IntroductionNEWS (April 09, 2005) : Axis C++1.5 Final is now available! NEWS ((March 01, 2005)) : Axis Axis 1.2 RC3 release is now available! NEWS (February 08, 2005) : Axis C++1.5 Alpha is now available! NEWS (December 16, 2004) : Axis C++1.4 Final is now available! NEWS (December 03, 2004) : Axis C++1.4 Alpha is now available! NEWS (November 16, 2004) : Axis 1.2 RC2 release is now available! NEWS (October 29, 2004) : Axis C++1.3 Final is now available! NEWS (September 30, 2004) : Axis 1.2 RC1 release is now available! NEWS (September 15, 2004) : Axis C++1.3 Beta is now available! NEWS (August 18, 2004) : Axis C++1.3 Alpha is now available! NEWS (August 17, 2004) : Axis 1.2 beta 3 release is now available! NEWS (July 14, 2004) : Axis 1.2 beta 2 release is now available! NEWS (July 09, 2004) : Axis C++1.2 is now available! NEWS (June 29, 2004) : Axis C++1.2 Beta is now available! NEWS (June 15, 2004) : Axis C++1.2 Alpha is now available! NEWS (May 07, 2004) : Axis C++1.1.1 is now available! NEWS (April 16, 2004) : Axis C++1.1 is now available! NEWS (March 31, 2004) : Axis 1.2 Beta is now available. NEWS (December 1, 2003) : Axis 1.2 Alpha is now available. NEWS (June 16, 2003) : Axis 1.1 Final is still the most recent stable release (read the release notes)! Apache Axis is an implementation of the SOAP ("Simple Object Access Protocol") submission to W3C. From the draft W3C specification: SOAP is a lightweight protocol for exchange of information in a decentralized, distributed environment. It is an XML based protocol that consists of three parts: an envelope that defines a framework for describing what is in a message and how to process it, a set of encoding rules for expressing instances of application-defined datatypes, and a convention for representing remote procedure calls and responses. This project is a follow-on to the Apache SOAP project. Please see the Reference Library for a list of technical resources that should prove useful. Axis 1.2 and beyondAxis 1.1 has proven itself to be a reliable and stable base on which to implement Java Web Services. There is a very active user community and there a many companies who use Axis for Web Service support in their products. For Axis 1.2, we are focusing on our document/literal support to better address the WS-I Basic Profile 1.0 and JAX-RPC 1.1 specifications. And we are fixing as many bug as possible. We can always use your help. Here are some links to help you help us: CreditsThe Axis Development Team WebServices - AxisWebServices - Axis - News(April 09, 2005) : Axis C++ 1.5 Final is available! (March 01, 2005) : Axis 1.2 RC3 release is now available! (February 08, 2005) : Axis C++ 1.5 Alpha is available! (December 16, 2004) : Axis C++ 1.4 Final is available! (December 03, 2004) : Axis C++ 1.4 Alpha is available! (November 16, 2004) : Axis 1.2 RC2 release is now available! (October 29, 2004) : Axis C++ 1.3 Final is available! (September 30, 2004) : Axis 1.2 RC1 release is now available! (September 15, 2004) : Axis C++ 1.3 Beta is available! (August 18, 2004) : Axis C++ 1.3 Alpha is available! (August 17, 2004) : Axis 1.2 beta 3 release is now available! (July 14, 2004) : Axis 1.2 beta 2 release is now available! (July 09, 2004) : Axis C++ 1.2 is available! (June 29, 2004) : Axis C++ 1.2 Beta is available! (June 15, 2004) : Axis C++ 1.2 Alpha is available! (May 07, 2004) : Axis C++ 1.1.1 is available! (April 16, 2004) : Axis C++ 1.1 is available! (December 29, 2003) : Axis C++ 1.0 is released! (December 01, 2003) : Axis 1.2 Alpha is available! (December 01, 2003) : Axis C++ Beta is available! (October 31, 2003) : Axis C++ alpha has been released! (September 10, 2003) : Axis CVS Repository has moved from xml-axis to ws-axis (June 16, 2003) : Axis 1.1 is now available! (March 5, 2003) : Axis 1.1 RC2 release is now available! (February 9, 2003) : Axis 1.1 RC1 release is now available! (October 7, 2002) : Axis 1.0 is now available! (September 30, 2002) : Axis 1.0 RC2 release is now available! (September 6, 2002) : Axis 1.0 RC1 release is now available! (July 9, 2002) : The Axis beta 3 release is available! See the Mailing Lists for more information. The Axis Development Team Get InvolvedWebServices - AxisWebServices - Axis - OverviewEvery volunteer project obtains its strength from the people involved in it. We invite you to participate as much or as little as you choose. The roles and responsibilities that people can assume in the project are based on merit. Everybody's input matters! There are a variety of ways to participate. Regardless of how you choose to participate, we suggest you join some or all of our mailing lists. Use the Products and Give Us Feedback Using the products,reporting bugs, making feature requests, etc. is by far the most important role. It's your feedback that allows the technology to evolve. Contribute Code or Documentation Patches In this role, you participate in the actual development of the code. If this is the type of role you'd like to play, here are some steps (in addition to the ones above) to get you started: WebServices - AxisWebServices - Axis - CVS RepositoriesMost users of the source code probably don't need to have day to day access to the source code as it changes. For these users we provide easy to unpack source code downloads via our download pages.
View the Source Tree
Latest CVS sources can be viewed at http://cvs.apache.org/viewcvs/ws-axis/
Access the Source Tree
(AnonCVS)
Anyone can checkout source code from our anonymous CVS server. To do so, simply use the following commands (if you are using a GUI CVS client, configure it appropriately): Full Remote CVS Access If you are a Committer and have a login on the Apache development server, this section is for you. If you are not a Committer, but you want to submit patches or even request commit privileges, please see the Jakarta GuideLines page (we follow the same rules) for more information. To have full access to the CVS server, you need to follow the links depending on the operating system you are using: WebServices - AxisWebServices - Axis - Mailing ListBefore subscribing to any of the mailing lists, please make sure you have read and understand the guidelines. While the mailing lists are not archived on Apache they are available at other sites, for example http://marc.theaimsgroup.com is pretty good and is used for searching below. The Axis User List
Medium Traffic
Subscribe
Unsubscribe
Subscribe(Digest)
Unsubscribe(Digest)
Send mail to list
The Axis Developer List
Medium Traffic
Subscribe
Unsubscribe
Subscribe(Digest)
Unsubscribe(Digest)
Send mail to list
The Axis C++ User List
Medium Traffic
Subscribe
Unsubscribe
Subscribe(Digest)
Unsubscribe(Digest)
Send mail to list
The Axis C++ Developer List
Medium Traffic
Subscribe
Unsubscribe
Subscribe(Digest)
Unsubscribe(Digest)
Send mail to list
WebServices - AxisWebServices - Axis - Reference LibraryThe Axis Project lives or fails based on its human resources. Users and contributors alike help the project with ideas and brainpower. A common foundation of knowledge is required to effectively participate in this virtual community. The following is a list of documents that we have found helpful for us and may be helpful to you: These resources are required reading for anybody contributing source code to the project. SOAP Specific Resources
SOAP W3C Specification
SOAP
Messaging with Attachments W3C Specification
SOAP Security
Extensions: Digital Signature Specification
Web Services Description Language (WSDL) 1.1 WS-I Basic Profile Version 1.0 Java API for XML-based RPC (JAX-RPC) Other Resources
The
Java Language Specification
Javadoc
The
Java Code Conventions
Open Source Development
with CVS
Introduction
to CVS
Version
Management with CVS
WebServices - AxisWebServices - Axis -New Axis bugs should be reported using JIRA (the Apache bug database).
Bugs related to WSDL4J should be addressed to the Expert Group for JSR110 at http://groups.yahoo.com/group/jsr110-eg-disc. For more information visit the following links: We also encourage you to write patches for problems you find and submit them to the axis-dev mailing list. If we agree the problem is a bug and the patch fixes it and does not break something else, we are likely to include the patch in the next release. How To Build Axis Project's WebsiteInstalling Forrest
The Axis website build system requires two components to perform a build. Specifically the build has been tested to work with Ant version 1.6.1 and Forrest 0.5.1. To install these products download the distributions and follow the instructions in their documentation. Make sure you don't forget to set the environment variables FORREST_HOME and ANT_HOME. The ANT_HOME/bin directory should be in the path. Checking out ws-axis and ws-site module
Check out 'ws-axis/site/src' and 'ws-site/target/axis'
module via your favorite CVS tools. Running the BuildHere's a list of targets for the ant task. But, what you need to do is just "ant".
For Committers (Highly recommended)The procedure to make changes to http://ws.apache.org/axis/ is:
Manual update (If you want to realize the value of ant tasks above ...)If you just want to update the site step-by-step, the followings are the instructions. 1. Installing Forrest [Note] At this time, the version 0.5.1 of Forrest is tested version. 2. Checking out 'ws-axis/site' module [ex] 'ws-axis/site/src/documentation/content/xdocs/java/user-guide.ihtml' 3. Make changes to the target 4. Confirming the change with "forrest run" 4-1) cd into the local "ws-axis/site" CVS dir 4-2) execute "forrest run" 4-3) have an access to http://localhost:8888/ to see the site 5. Generating a static content with "forrest" 5-1) execute "forrest" in the "ws-axis/site" dir 5-2) check the generated contents in "ws-axis/site/build/site/" 6. Make commitments 6-1) commit the original source (xml/ihtml/gif/jpg) to "ws-axis" 6-2) copy the generated contents into "ws-site/targets/axis" 6-3) commit the generated contents to "ws-site" 7. (Optional) If you are in a hurry to reflect the change to the site, cd to /www/ws.apache.org, and execute "cvs update -P" on minotaur. [Note] *** VERY IMPORTANT *** YOU HAVE TO CHECK YOUR UMASK IS "002" BEFORE DOING THE COMMAND, OR THE SITE WILL BECOME A NON-UPDATABLE SITE FROM THEN ON. The site will be updated automatically twice a day 12 midnight and 12 noon PST by a cron job of dims. F.A.Q.
Q1.
A1.
Q2.
A2.
( more to be come ) Axis (Java)Axis DocumentationDocumentationThis is the documentation for Apache Axis 1.2 If the version of Axis you are using is older or newer than this version, then this is the wrong documentation to be using. Read the version that came with your copy of Axis. Documentation for Axis Users
Documentation for Axis Developers
Axis installation instructionsAxis installation instructionsContents
IntroductionThis document describes how to install Apache Axis. It assumes you already know how to write and run Java code and are not afraid of XML. You should also have an application server or servlet engine and be familiar with operating and deploying to it. If you need an application server, we recommend Jakarta Tomcat. [If you are installing Tomcat, get the latest 4.1.x version, and the full distribution, not the LE version for Java 1.4, as that omits the Xerces XML parser]. Other servlet engines are supported, provided they implement version 2.2 or greater of the servlet API. Note also that Axis client and server requires Java 1.3 or later. For more details on using Axis, please see the user guide. Things you have to knowA lot of problems with Axis are encountered by people who are new to Java, server-side Java and SOAP. While you can learn about SOAP as you go along, writing Axis clients and servers is not the right time to be learning foundational Java concepts, such as what an array is, or basic application server concepts such as how servlets work, and the basics of the HTTP protocol. Things you need to know before writing a Web Service:
Axis and SOAP depends on all these details. If you don't know them, Axis (or anyone else's Web Service middleware) is a dangerous place to learn. Sooner or later you will be forced to discover these details, and there are easier places to learn than Axis. If you are completely new to Java, we recommend you start off with things like the Java Tutorials on Sun's web site, and perhaps a classic book like Thinking in Java, until you have enough of a foundation to be able to work with Axis. It is also useful to have written a simple web application, as this will give you some knowledge of how HTTP works, and how Java application servers integrate with HTTP. You may find the course notes from Mastering the World Wide Web useful in this regard, even though Axis is only introduced in lecture 28. Be aware that there is a lot more needed to be learned in order to use Axis and SOAP effectively than the listing above. The other big area is "how to write internet scale distributed applications". Nobody knows how to do that properly yet, so that you have to learn this by doing. Step 0: ConceptsApache Axis is an Open Source SOAP server and client. SOAP is a mechanism for inter-application communication between systems written in arbitrary languages, across the Internet. SOAP usually exchanges messages over HTTP: the client POSTs a SOAP request, and receives either an HTTP success code and a SOAP response or an HTTP error code. Open Source means that you get the source, but that there is no formal support organisation to help you when things go wrong. SOAP messages are XML messages. These messages exchange structured information between SOAP systems. Messages consist of one or more SOAP elements inside an envelope, Headers and the SOAP Body. SOAP has two syntaxes for describing the data in these elements, Section 5, which is a clear descendant of the XML RPC system, and XML Schema, which is the newer (and usually better) system. Axis handles the magic of converting Java objects to SOAP data when it sends it over the wire or receives results. SOAP Faults are sent by the server when something goes wrong; Axis converts these to Java exceptions. SOAP is intended to link disparate systems. It is not a mechanism to tightly bind Java programs written by the same team together. It can bind Java programs together, but not as tightly as RMI or Corba. If you try sending many Java objects that RMI would happily serialize, you will be disappointed at how badly Axis fails. This is by design: if Axis copied RMI and serialized Java objects to byte streams, you would be stuck to a particular version of Java everywhere. Axis implements the JAX-RPC API, one of the standard ways to program Java services. If you look at the specification and tutorials on Sun's web site, you will understand the API. If you code to the API, your programs will work with other implementations of the API, such as those by Sun and BEA. Axis also provides extension features that in many ways extends the JAX-RPC API. You can use these to write better programs, but these will only work with the Axis implementation. But since Axis is free and you get the source, that should not matter. Axis is compiled in the JAR file axis.jar; it implements the JAX-RPC API declared in the JAR files jaxrpc.jar and saaj.jar. It needs various helper libraries, for logging, WSDL processing and introspection. All these files can be packaged into a web application, axis.war, that can be dropped into a servlet container. Axis ships with some sample SOAP services. You can add your own by adding new compiled classes to the Axis webapp and registering them. Before you can do that, you have to install it and get it working. Step 1: Preparing the webappHere we assume that you have a web server up and running on the localhost at port 8080. If your server is on a different port, replace references to 8080 to your own port number. In your Application Server installation, you should find a directory into which web applications ("webapps") are to be placed. Into this directory copy the webapps/axis directory from the xml-axis distribution. You can actually name this directory anything you want, just be aware that the name you choose will form the basis for the URL by which clients will access your service. The rest of this document assumes that the default webapp name, "axis" has been used; rename these references if appropriate. Step 2: Setting up the librariesIn the Axis directory, you will find a WEB-INF sub-directory. This directory contains some basic configuration information, but can also be used to contain the dependencies and web services you wish to deploy. Axis needs to be able to find an XML parser. If your application server or Java runtime does not make one visible to web applications, you need to download and add it. Java 1.4 includes the Crimson parser, so you can omit this stage, though the Axis team prefer Xerces. To add an XML parser, acquire the JAXP 1.1 XML compliant parser of your choice. We recommend Xerces jars from the xml-xerces distribution, though others mostly work. Unless your JRE or app server has its own specific requirements, you can add the parser's libraries to axis/WEB-INF/lib. The examples in this guide use Xerces. This guide adds xml-apis.jar and xercesImpl.jar to the AXISCLASSPATH so that Axis can find the parser (see below). If you get ClassNotFound errors relating to Xerces or DOM then you do not have an XML parser installed, or your CLASSPATH (or AXISCLASSPATH) variables are not correctly configured. Tomcat 4.x and Java 1.4Java 1.4 changed the rules as to how packages beginning in java.* and javax.* get loaded. Specifically, they only get loaded from endorsed directories. jaxrpc.jar and saaj.jar contain javax packages, so they may not get picked up. If happyaxis.jsp (see below) cannot find the relevant packages, copy them from axis/WEB-INF/lib to CATALINA_HOME/common/lib and restart Tomcat. WebLogic 8.1WebLogic 8.1 ships with webservices.jar that conflicts with Axis' saaj.jar and prevents Axis 1.2 from working right out of the box. This conflict exists because WebLogic uses an older definition of javax.xml.soap.* package from Java Web Services Developer Pack Version 1.0, whereas Axis uses a newer revision from J2EE 1.4. However, there are two alternative configuration changes that enable Axis based web services to run on Weblogic 8.1.
For more information on how WebLogic's class loader works, see WebLogic Server Application Classloading. Step 3: starting the web serverThis varies on a product-by-product basis. In many cases it is as simple as double clicking on a startup icon or running a command from the command line. Step 4: Validate the InstallationAfter installing the web application and dependencies, you should make sure that the server is running the web application. Look for the start pageNavigate to the start page of the webapp, usually http://127.0.0.1:8080/axis/, though of course the port may differ. Validate Axis with happyaxisFollow the link Validate the local installation's configuration
If any of the needed libraries are missing, Axis will not work. Look for some servicesFrom the start page, select View the list of deployed Web services. This will list all registered Web Services, unless the servlet is configured not to do so. On this page, you should be able to click on (wsdl) for each deployed Web service to make sure that your web service is up and running. Note that the 'instant' JWS Web Services that Axis supports are not listed in this listing here. The install guide covers this topic in detail. Test a SOAP EndpointNow it's time to test a service. Although SOAP 1.1 uses HTTP POST to submit an XML request to the endpoint, Axis also supports a crude HTTP GET access mechanism, which is useful for testing. First let's retrieve the version of Axis from the version endpoint, calling the getVersion method: <?xml version="1.0" encoding="UTF-8" ?> The Axis version and build date may of course be different. Test a JWS EndpointNow let's test a JWS web service. Axis' JWS Web Services are java files you save into the Axis webapp anywhere but the WEB-INF tree, giving them the .jws extension. When someone requests the .jws file by giving its URL, it is compiled and executed. The user guide covers JWS pages in detail. To test the JWS service, we make a request against a built-in example, EchoHeaders.jws (look for this in the axis/ directory). Point your browser at http://localhost:8080/axis/EchoHeaders.jws?method=list. This should return an XML listing of your application headers, such as <?xml version="1.0" encoding="UTF-8" ?> Again, the exact return values will be different, and you may need to change URLs to correct any host, port and webapp specifics. Step 5: Installing new Web ServicesSo far you have got Axis installed and working--now it is time to add your own Web Service. The process here boils down to (1) get the classes and libraries of your new service into the Axis WAR directory tree, and (2) tell the AxisEngine about the new file. The latter is done by submitting an XML deployment descriptor to the service via the Admin web service, which is usually done with the AdminClient program or the <axis-admin> Ant task. Both of these do the same thing: they run the Axis SOAP client to talk to the Axis administration service, which is a SOAP service in its own right. It's also a special SOAP service in one regard--it is restricted to local callers only (not remote access) and is password protected to stop random people from administrating your service. There is a default password that the client knows; if you change it then you need to pass the new password to the client. The first step is to add your code to the server. In the WEB-INF directory, look for (or create) a "classes" directory (i.e. axis/WEB-INF/classes ). In this directory, copy the compiled Java classes you wish to install, being careful to preserve the directory structure of the Java packages. If your classes services are already packaged into JAR files, feel free to drop them into the WEB-INF/lib directory instead. Also add any third party libraries you depend on into the same directory. After adding new classes or libraries to the Axis webapp, you must restart the webapp. This can be done by restarting your application server, or by using a server-specific mechanism to restart a specific webapp. Note: If your web service uses the simple authorization handlers provided with xml-axis (this is actually not recommended as these are merely illustrations of how to write a handler than intended for production use), then you will need to copy the corresponding users.lst file into the WEB-INF directory. Step 6: Deploying your Web ServiceThe various classes and JARs you have just set up implement your new Web Service. What remains to be done is to tell Axis how to expose this web service. Axis takes a Web Service Deployment Descriptor (WSDD) file that describes in XML what the service is, what methods it exports and other aspects of the SOAP endpoint. The users guide and reference guide cover these WSDD files; here we are going to use one from the Axis samples: the stock quote service. Classpath setupIn order for these examples to work, java must be able to find axis.jar, commons-discovery.jar, commons-logging.jar, jaxrpc.jar, saaj.jar, log4j-1.2.8.jar (or whatever is appropriate for your chosen logging implementation), and the XML parser jar file or files (e.g., xerces.jar). These examples do this by adding these files to AXISCLASSPATH and then specifying the AXISCLASSPATH when you run them. Also for these examples, we have copied the xml-apis.jar and xercesImpl.jar files into the AXIS_LIB directory. An alternative would be to add your XML parser's jar file directly to the AXISCLASSPATH variable or to add all these files to your CLASSPATH variable. set AXIS_HOME=c:\axis Unix users have to do something similar. Below we have installed AXIS into /usr/axis and are using the bash shell. See your shell's documentation for differences. To make variables permeate you will need to add them to your shell's startup (dot) files. Again, see your shell's documentation. set AXIS_HOME=/usr/axis To use Axis client code, you can select AXISCLASSPATH when invoking Java by entering java -cp %AXISCLASSPATH% ... or java -cp "$AXISCLASSPATH" ... depending on the platform. You may omit the quotes if your CLASSPATH doesn't have spaces in it. Find the deployment descriptorLook in axis/samples/stock for the file deploy.wsdd. This is the deployment descriptor we want to tell Axis about. Deployment descriptors are an Axis-specific XML file that tells Axis how to deploy (or undeploy) a Web Service, and how to configure Axis itself. The Axis Administration Web Service lets the AdminClient program and its Ant task counterpart submit a new WSDD file for interpretation. The Axis 'engine' will update its configuration, then save its state. By default Axis saves it state into the global configuration file axis/WEB-INF/server-config.wsdd. Sometimes you see a warning message about such a file not being found--don't worry about this, because Axis auto-creates the file after you deploy something to it. You can check in the webapp to see what this file looks like--and even copy it to other systems if you want to give them identical configurations. Note that Axis needs an expanded web application and write access to the WEB-INF dir to save its state in this location. Run the admin clientExecute the following command from the samples/stock directory. If you are not in this directory you will get a "java.io.FileNotFoundException: deploy.wsdd (The system cannot find the file specified)" exception.
If you get some java client error (like ClassNotFoundException), then you haven't set up your AXISCLASSPATH (or CLASSPATH) variable right, mistyped the classname, or did some other standard error. Tracking down such problems are foundational Java development skills--if you don't know how to do these things, learn them now! Note: You may need to replace localhost with your host name, and 8080 with the port number used by your web server. If you have renamed the web application to something other than "axis" change the URL appropriately. If you get some AxisFault listing, then the client is working, but the deployment was unsuccessful. This is where the knowledge of the sockets API to TCP and the basics of the HTTP that Web Service development requires begins to be needed. If you got some socket error like connection refused, the computer at the far end isn't talking to you, so find the cause of that and fix it. If you get an HTTP error code back find out what the error means and correct the problem. These skills are fundamental to using web services. The user's guide covers the AdminClient in more detail, and there is also an Ant task to automate the use of Axis in your Ant build scripts. Step 7: TestingThis step is optional, but highly recommended. For illustrative purposes, it is presumed that you have installed and deployed the stock quote demo.
Note: Again, you may need to replace localhost with your host name, and 8080 with the port number used by your web server. If you have renamed the web application to something other than "axis" change the URL appropriately. Advanced Installation: adding Axis to your own WebappIf you are experienced in web application development, and especially if you wish to add web services to an existing or complex webapp, you can take an alternate approach to running Axis. Instead of adding your classes to the Axis webapp, you can add Axis to your application. The core concepts are
The process is also covered in Chapter 15 of Java Development with Ant, which can be downloaded as a PDF file. What if it doesn't work?Axis is a complicated system to install. This is because it depends on the underlying functionality of your app server, has a fairly complex configuration, and, like all distributed applications, depends upon the network too. We see a lot of people posting their problems on the axis-user mailing list, and other Axis users as well as the Axis developers do their best to help when they can. But before you rush to post your own problems to the mailing list, a word of caution: Axis is free. This means nobody gets paid to man the support lines. All the help you get from the community is voluntary and comes from the kindness of their hearts. They may be other users, willing to help you get past the same hurdles they had to be helped over, or they may be the developers themselves. But it is all voluntary, so you may need to keep your expectations low!
Has this put you off joining and participating in the Axis user mail list? We hope not--this list belongs to the people who use Axis and so will be your peers as your project proceeds. We just need for you to be aware that it is not a 24x7 support line for people new to server side Java development, and that you will need to be somewhat self sufficient in this regard. It is not a silver bullet. However, knowing how to make effective use of the list will help you develop better with Axis. SummaryAxis is simply an implementation of SOAP which can be added to your own webapp, and a webapp which can host your own web services. Installing it can be a bit fiddly, especially given Java 1.4's stricter requirements. If you follow a methodical process, including testing along the way, using happyaxis and the bundled test services, you will find it easier to get started with Axis. Appendix: Enabling the SOAP MonitorSOAP Monitor allows for the monitoring of SOAP requests and responses via a web browser with Java plug-in 1.3 or higher. For a more comprehensive explanation of its usage, read Using the SOAP Monitor in the User's Guide. By default, the SOAP Monitor is not enabled. The basic steps for enabling it are compiling the SOAP Monitor java applet, deploying the SOAP Monitor web service and adding request and response flow definitions for each monitored web service. In more detail:
Axis User's GuideAxis User's Guide
1.2 Version
Table of Contents
IntroductionWelcome to Axis, the third generation of Apache SOAP! What is SOAP?SOAP is an XML-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, SOAP 1.2, though version 1.1 is more widespread. The W3C's XML Protocol working group is in charge of the specification. SOAP is widely viewed as the backbone to a new generation of cross-platform cross-language distributed computing applications, termed Web Services. What is Axis?Axis is essentially a SOAP engine -- 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. But Axis isn't just a SOAP engine -- it also includes:
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. 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. After months of continued discussion and coding effort in this direction, Axis now delivers the following key features:
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 Axis stands for, it's Apache EXtensible Interaction System - a fancy way of implying it's a very configurable SOAP engine. Let us know what you think!Please send feedback about the package to "axis-user@ws.apache.org". Also, Axis is registered in jira, the Apache bug tracking and feature-request database. What's in this release?This release includes the following features:
What's still to do?Please click for a list of what we think needs doing - and please consider helping out if you're interested & able! Installing Axis and Using this GuideSee the Axis Installation Guide for instructions on installing Axis as a web application on your J2EE server. 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):
Consuming Web Services with AxisBasics - Getting StartedLet's take a look at an example Web Service client that will call the echoString method on the public Axis server at Apache. 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://ws.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("http://soapinterop.org/", echoString")); 16 17 String ret = (String) call.invoke( new Object[] { "Hello!" } ); 18 19 System.out.println("Sent 'Hello!', got '" + ret + "'"); 20 } catch (Exception e) { 21 System.err.println(e.toString()); 22 } 23 } 24 } (You'll find this file in samples/userguide/example1/TestClient.java) Assuming you have a network connection active, this program can be run as follows: % java samples.userguide.example1.TestClient Sent 'Hello!', got 'Hello!' % 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. 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): <?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/"> <arg0 xsi:type="xsd:string">Hello!</arg0> </ns1:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope> The String argument is automatically serialized into XML, and the server responds with an identical String, which we deserialize and print. Note: To actually watch the XML flowing back and forth between a SOAP client and server, you can use the included tcpmon tool or SOAP monitor tool. See the appendix for an overview. Naming ParametersIn 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 invoke() you need to call addParameter for each parameter and setReturnType for the return, like so: call.addParameter("testParam", org.apache.axis.Constants.XSD_STRING, javax.xml.rpc.ParameterMode.IN); call.setReturnType(org.apache.axis.Constants.XSD_STRING); This will assign the name testParam to the 1st (and only) parameter on the invoke call. This will also define the type of the parameter (org.apache.axis.Constants.XSD_STRING) 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: <?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/"> <testParam xsi:type="xsd:string">Hello!</testParam> </ns1:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Note that the param is now named "testParam" as expected. Interoperating with "untyped" serversIn 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 :)). Here's what a typical response might look like to the echoString method: <?xml version="1.0" encoding="UTF-8"?> Take a look at the section which we've highlighted in red - that attribute is a schema type declaration, 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: <?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> 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 metadata - data about data. In this case, we need a description 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: call.setReturnType( org.apache.axis.Constants.XSD_STRING ); 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.) There is also a similar method which allows you to specify the Java class of the expected return type: call.setReturnClass(String.class); OK - so now you know the basics of accessing SOAP services as a client. But how do you publish your own services? Publishing Web Services with AxisLet's say we have a simple class like the following: public class Calculator { public int add(int i1, int i2) { return i1 + i2; } public int subtract(int i1, int i2) { return i1 - i2; } } (You'll find this very class in samples/userguide/example2/Calculator.java.) 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! JWS (Java Web Service) Files - Instant DeploymentOK, 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: % copy Calculator.java <your-webapp-root>/axis/Calculator.jws 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): http://localhost:8080/axis/Calculator.jws 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: % java samples.userguide.example2.CalcClient -p8080 add 2 5 Got result : 7 % java samples.userguide.example2.CalcClient -p8080 subtract 10 9 Got result : 1 % (Note that you may need to replace the "-p8080" with whatever port your J2EE server is running on) Important: 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. Custom Deployment - Introducing WSDDJWS 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. (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!) Deploying via descriptorsTo really use the flexibility available to you in Axis, you should get familiar with the Axis Web Service Deployment Descriptor (WSDD) 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 samples/userguide/example3/deploy.wsdd): <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> 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 targeted chain (see the Architecture Guide), 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 org.apache.axis.providers.java.RPCProvider. We'll go into more detail later on the different styles of services and their providers. 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). Advanced WSDD - specifying more optionsWSDD descriptors can also contain other information about services, and also other pieces of Axis called "Handlers" which we'll cover in a later section. Scoped ServicesAxis 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 all 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 "value" is request, session, or application): <service name="MyService"...> <parameter name="scope" value="value"/> ... </service> Using the AdminClientOnce 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 <port> argument. The default port is 8080. A typical invocation of the AdminClient looks like this: % java org.apache.axis.client.AdminClient deploy.wsdd <Admin>Done processing</Admin> This command has now made our service accessible via SOAP. Check it out by running the Client class - it should look like this: % java samples.userguide.example3.Client -lhttp://localhost:8080/axis/services/MyService "test me!" You typed : test me! % 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. You can also use the AdminClient to get a listing of all the deployed components in the server: % java org.apache.axis.client.AdminClient list <big XML document returned here> 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. More deployment - Handlers and ChainsNow 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): <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" provider="java:RPC"> <requestFlow> <handler type="track"/> </requestFlow> <parameter name="className" value="samples.userguide.example4.Service"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> 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. 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. Remote AdministrationNote 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 true. 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: <service name="AdminService" provider="java:MSG"> <parameter name="className" value="org.apache.axis.util.Admin"/> <parameter name="allowedMethods" value="*"/> <parameter name="enableRemoteAdmin" value="true"/> </service> 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! Service Styles - RPC, Document, Wrapped, and MessageThere are four "styles" of service in Axis. RPC services use the SOAP RPC conventions, and also the SOAP "section 5" encoding. Document 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. Wrapped 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. Message 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. RPC servicesRPC 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.) Document / Wrapped servicesDocument 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 databinding section for more), so you end up dealing with Java objects, not directly with XML constructs. A good place to start in describing the difference between document and wrapped services is with a sample SOAP message containing a purchase order: <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> The relevant schema for the PurchaseOrder looks like this: <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"/> </schema> For a document style service, this would map to a method like this: public void method(PurchaseOrder po) 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 wrapped style service, it would map to a method like this: public void purchaseOrder(String item, int quantity, String description) 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. The document or wrapped style is indicated in WSDD as follows: <service ... style="document"><service ... style="document"> for document style In most cases you won't need to worry about document or wrapped services if you are starting from a WSDL document (see below). Message servicesFinally, 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: public Element [] method(Element [] bodies); public SOAPBodyElement [] method (SOAPBodyElement [] bodies); public Document method(Document body); public void method(SOAPEnvelope req, SOAPEnvelope resp); 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. The third signature will pass you a DOM Document representing the <soap:body>, and expects the same in return. 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. Message Example A sample message service can be found in samples/message/MessageService.java. The service class, MessageService, has one public method, echoElements, which matches the first of the three method signatures above: public Element[] echoElements(Element [] elems) The MsgProvider handler calls the method with an array of org.w3c.dom.Element 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 Element[] array to be returned in the SOAP body of the response message. Message services must be deployed with a WSDD file. Here is the full WSDD for the MessageService class: <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" style="message"> <parameter name="className" value="samples.message.MessageService"/> <parameter name="allowedMethods" value="echoElements"/> </service> 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 org.apache.axis.providers.java.MsgProvider rather than org.apache.axis.providers.java.RPCProvider. You can test this service by deploying it, then running samples.message.TestMsg (look at the source to see what the test driver does). XML <-> Java Data Mapping in AxisHow your Java types map to SOAP/XML typesInteroperability, interop, 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 external articles 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 specification to fully understand how things are converted. Here are some of the salient points. Standard mappings from WSDL to Java
If the WSDL says that an object can be nillable, that is the caller may choose to return a value of nil, then the primitive data types are replaced by their wrapper classes, such as Byte, Double, Boolean, etc. SOAP Encoding DatatypesAlongside 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. ExceptionsThis 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 RemoteExceptions map to SOAP FaultsIf the server method throws a java.rmi.RemoteException then this will be mapped into a SOAP Fault. The faultcode of this will contain the classname of the fault. The recipient is expected to deserialize the body of the fault against the classname. 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 java.rmi.RemoteException instances, rather than subclasses. 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. Exceptions are represented as wsdl:fault elementsIf a method is marked as throwing an Exception that is not an instance or a subclass of java.rmi.RemoteException, then things are subtly different. The exception is no longer a SOAP Fault, but described as a wsdl:fault 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 and 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 JavaBean. The fields in the object must be of the datatypes that can be reliably mapped into WSDL. 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. 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. Java CollectionsSome of the Collection classes, such as Hashtable, 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. Arbitrary Objects without Pre-RegistrationYou 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 Serializable Java objects, but that is because you are running Java at both ends. Axis will only send objects for which there is a registered Axis serializer. 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. Remote ReferencesRemote 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 HashMap with numeric or string keys that can be passed over the wire. What Axis can send via SOAP with restricted InteroperabilityWhat Axis can not send via SOAPEncoding Your Beans - the BeanSerializerAxis includes the ability to serialize/deserialize, without writing any code, arbitrary Java classes which follow the standard JavaBean 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: <beanMapping qname="ns:local" xmlns:ns="someNamespace" languageSpecificType="java:my.java.thingy"/> The <beanMapping> tag maps a Java class (presumably a bean) to an XML QName. You'll note that it has two important attributes, qname and languageSpecificType. So in this case, we'd be mapping the "my.java.thingy" class to the XML QName [someNamespace]:[local]. Let's take a look at how this works in practice. Go look at samples/userguide/example5/BeanService.java. 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): % 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. % When Beans Are Not Enough - Custom SerializationJust 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. 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. Deploying custom mappings - the <typeMapping> tagNow 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: <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/"/> This looks a lot like the <beanMapping> tag we saw earlier, but there are three extra attributes. One, serializer, is the Java class name of the Serializer factory which gets the serializer to be used to marshal an object of the specified Java class (i.e., my.java.thingy) into XML. Another, deserializer, is the class name of a Deserializer factory that gets the deserializer to be used to unmarshall XML into the correct Java class. The final attribute, the encodingStyle, which is SOAP encoding. (The <beanMapping> tag is really just shorthand for a <typeMapping> tag with serializer="org.apache.axis.encoding.ser.BeanSerializerFactory", deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory", and encodingStyle="http://schemas.xmlsoap.org/soap/encoding/", but clearly it can save a lot of typing!) Using WSDL with AxisThe Web Service Description Language 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. Axis supports WSDL in three ways:
?WSDL: Obtaining WSDL for deployed servicesWhen 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>". 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. You can also generate WSDL files from existing Java classes (see Java2WSDL: Building WSDL from Java ). WSDL2Java: Building stubs, skeletons, and data types from WSDLClient-side bindingsYou'll find the Axis WSDL-to-Java tool in "org.apache.axis.wsdl.WSDL2Java". The basic invocation form looks like this: % java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL) 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: % cd samples/addr % java org.apache.axis.wsdl.WSDL2Java AddressBook.wsdl 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.
There is an Ant Task to integrate this action with an Ant based build process. TypesThe 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 Address Book sample): <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> WSDL2Java will generate: 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() {...} } Mapping XML to Java types : MetadataNotice 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. To support this kind of mapping, and also to enable the serialization/deserialization of XML attributes, we have a type metadata system which allows us to associate Java data classes with descriptors which control these things. 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 type descriptor for the class. The type descriptor is essentially a collection of field descriptors, each of which maps a Java field/property to an XML element or attribute. 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. HoldersThis 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: 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; } } A holder class is only 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". The holder classes for the primitive types can be found in javax.xml.rpc.holders. PortTypesThe 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: <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> WSDL2Java will generate: public interface AddressBook extends java.rmi.Remote { public void addEntry(String name, Address address) throws java.rmi.RemoteException; } 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 and the binding. (This is unfortunate and is a topic of discussion for WSDL version 2.) 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." 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. 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). 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. BindingsA 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 proxy (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. Given the following WSDL snippet: <binding name="AddressBookSOAPBinding" type="tns:AddressBook"> ... </binding> WSDL2Java will generate: 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 {...} ServicesNormally, 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: <service name="AddressBookService"> <port name="AddressBook" binding="tns:AddressBookSOAPBinding"> <soap:address location="http://localhost:8080/axis/services/AddressBook"/> </port> </service> WSDL2Java will generate the service interface: public interface AddressBookService extends javax.xml.rpc.Service { public String getAddressBookAddress(); WSDL2Java will also generate the locator which implements this interface: public class AddressBookServiceLocator extends org.apache.axis.client.Service implements AddressBookService { ... } 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. A typical usage of the stub classes would be as follows: 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); } Server-side bindingsJust as a stub is the client side of a Web Service represented in Java, a skeleton 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: % java org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true AddressBook.wsdl You will see that WSDL2Java generates all the classes that were generated before for the client, but it generates a few new files:
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: % java org.apache.axis.wsdl.WSDL2Java --server-side AddressBook.wsdl And here are the server side files that are generated:
BindingsSkeleton Description (for Skeleton Deployment)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: 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); } } (The real skeleton is actually much richer. For brevity we just show you the basic skeleton.) 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. Implementation Template DescriptionWSDL2Java also generates an implementation template from the binding: public class AddressBookSOAPBindingImpl implements AddressBook { 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. 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. ServicesThe 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. Java2WSDL: Building WSDL from JavaThe 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. Step 1: Provide a Java interface or classWrite 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 (samples/userguide/example6/WidgetPrice.java): package samples.userguide.example6; Note: If you compile your class with debug information, Java2WSDL will use the debug information to obtain the method parameter names. Step 2: Create WSDL using Java2WSDLUse the Java2WSDL tool to create a WSDL file from the interface above. Here is an example invocation that produces the wsdl file (wp.wsdl) from the interface described in the previous section: % 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 Where:
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. The Java2WSDL tool has many additional options which are detailed in the reference guide. There is an Ant Task to integrate this action with an Ant based build process. Step 3: Create Bindings using WSDL2JavaUse the generated WSDL file to build the appropriate client/server bindings for the web service (see WSDL2Java): % java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true -Nurn:Example6 samples.userguide.example6 wp.wsdl This will generate the following files:
Now you have all of the necessary files to build your client/server side code and deploy the web service! Published Axis InterfacesAlthough 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. Hence certain interfaces are designated as published, 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. 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 axis-user mailing list. The current list of published interfaces is as follows:
Newbie Tips: Finding Your Way AroundSo 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 somewhere, 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. Places to Look for CluesHere are the big categories.
Classes to Knoworg.apache.axis.MessageContextThe 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:
From within your service, the current MessageContext object is always available via the static method MessageContext.getCurrentContext(). 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. org.apache.axis.MessageAn org.apache.axis.Message 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:
org.apache.axis.SOAPEnvelopeAs 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. Appendix : Using the Axis TCP Monitor (tcpmon)The included "tcpmon" utility can be found in the org.apache.axis.utils package. To run it from the command line: % java org.apache.axis.utils.tcpmon [listenPort targetHost targetPort] Without any of the optional arguments, you will get a gui which looks like this:
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:
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. 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. Appendix: Using the SOAP MonitorWeb 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. 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. 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). 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. 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. Glossary
Axis Developer's GuideAxis Developer's Guide
1.2 Version
IntroductionThis guide is a collection of topics related to developing code for Axis. General Guidelines
Development EnvironmentThe following packages are required for axis development:
G:\xerces\xerces-1_4_2\xerces.jar G:\junit3.7\junit.jar G:\xml-axis\java\build\lib\commons-discovery.jar G:\xml-axis\java\build\lib\commons-logging.jar G:\xml-axis\java\build\lib\wsdl4j.jar G:\xml-axis\java\build\lib\axis.jar G:\xml-axis\java\build\lib\log4j-1.2.8.jar G:\xml-axis\java\build\classes If you access the internet via a proxy server, you'll need to set an environment variable so that the Axis tests do the same. Set ANT_OPTS to, for example: -Dhttp.proxyHost=proxy.somewhere.com -Dhttp.proxyPort=80 -Dhttp.nonProxyHosts="localhost" Pluggable-ComponentsThe Axis Architecture Guide explains the requirements for pluggable components. DiscoveryAn Axis-specific component factory should be created of the form: org.apache.axis.components.<componentType>.<factoryClassName>For example, org.apache.axis.components.logger.LogFactory is the factory, or discovery mechanism, for the logger component/service. The org.apache.axis.components.image package demonstrates both a factory, and supporting classes for different image tools used by Axis. This is representative of a pluggable component that uses external tooling, isolating it behind a 'thin' wrapper to Axis that provides only a limited interface to meet Axis minimal requirements. This allows future designers and implementors to gain an explicit understanding of the Axis's specific requirements on these tools. Logging/TracingAxis logging and tracing is based on the Logging component of the Jakarta Commons project, or the Jakarta Commons Logging (JCL) SPI. The JCL provides a Log interface with thin-wrapper implementations for other logging tools, including Log4J, Avalon LogKit, and JDK 1.4. The interface maps closely to Log4J and LogKit. Using the Logger SPITo use the JCL SPI from a Java class, include the following import statements: import org.apache.commons.logging.Log; import org.apache.axis.components.logger.LogFactory; For each class definition, declare and initialize a log attribute as follows: public class CLASS { private static Log log = LogFactory.getLog(CLASS.class); ... Messages are logged to a logger, such as log by invoking a method corresponding to priority: The Log interface defines the following methods for use in writing log/trace messages to the log: log.fatal(Object message); log.fatal(Object message, Throwable t); log.error(Object message); log.error(Object message, Throwable t); log.warn(Object message); log.warn(Object message, Throwable t); log.info(Object message); log.info(Object message, Throwable t); log.debug(Object message); log.debug(Object message, Throwable t); log.trace(Object message); log.trace(Object message, Throwable t); While semantics for these methods are ultimately defined by the implementation of the Log interface, it is expected that the severity of messages is ordered as shown in the above list. In addition to the logging methods, the following are provided: log.isFatalEnabled(); log.isErrorEnabled(); log.isWarnEnabled(); log.isInfoEnabled(); log.isDebugEnabled(); log.isTraceEnabled(); These are typically used to guard code that only needs to execute in support of logging, and that introduces undesirable runtime overhead in the general case (logging disabled). GuidelinesMessage PrioritiesIt is important to ensure that log message are appropriate in content and severity. The following guidelines are suggested:
Configuring the LoggerThe Jakarta Commons Logging (JCL) SPI can be configured to use different logging toolkits. To configure which logger is used by the JCL, see the Axis System Integration Guide. Configuration of the behavior of the JCL ultimately depends upon the logging toolkit being used. The JCL SPI (and hence Axis) uses Log4J by default if it is available (in the CLASSPATH). Log4JAs Log4J is the prefered/default logger for Axis, a few details are presented herein to get the developer going. Configure Log4J using system properties and/or a properties file:
Axis Servlet Query String Plug-insAny servlet that is derived from the org.apache.axis.transport.http.AxisServlet class supports a number of standard query strings (?list, ?method, and ?wsdl) that provide information from or perform operations on a web service (for instance, ?method is used to invoke a method on a web service and ?wsdl is used to retrieve the WSDL document for a web service). Axis servlets are not limited to these three query strings and developers may create their own "plug-ins" by implementing the org.apache.axis.transport.http.QSHandler interface. There is one method in this interface that must be implemented, with the following signature: public void invoke (MessageContext msgContext) throws AxisFault; The org.apache.axis.MessageContext instance provides the developer with a number of useful objects (such as the Axis engine instance, and HTTP servlet objects) that are accessible by its getProperty method. The following constants can be used to retrieve various objects provided by the Axis servlet invoking the query string plug-in:
Query string plug-in development is much like normal servlet development since the same basic information and methods of output are available to the developer. Below is an example query string plug-in which simply displays the value of the system clock (import statements have been omitted for brevity): public class QSClockHandler implements QSHandler { public void invoke (MessageContext msgContext) throws AxisFault { PrintWriter out = (PrintWriter) msgContext.getProperty (HTTPConstants.PLUGIN_WRITER); HttpServletResponse response = (HttpServletResponse) msgContext.getProperty (HTTPConstants.MC_HTTP_SERVLETRESPONSE); response.setContentType ("text/html"); out.println ("<HTML><BODY><H1>" + System.currentTimeMillis() + "</H1></BODY></HTML>"); } } Once a query string plug-in class has been created, the Axis server must be set up to recognize the query string which invokes it. See the section Deployment (WSDD) Reference in the Axis Reference Guide for information on how the HTTP transport section of the Axis server configuration file must be set up. Configuration PropertiesAxis is in the process of moving away from using system properties as the primary point of internal configuration. Avoid calling System.getProperty(), and instead call AxisProperties.getProperty. AxisProperties.getProperty will call System.getProperty, and will (eventually) query other sources of configuration information. Using this central point of access will allow the global configuration system to be redesigned to better support multiple Axis engines in a single JVM. Exception HandlingGuidelines for Axis exception handling are based on best-practices for exception handling. While there are details specific to Axis in these guidelines, they apply in principle to any project; they are included here for two reasons. First, because they are not listed elsewhere in the Apache/Jakarta guidelines (or haven't been found). Second, because adherence to these guidelines is considered crucial to enterprise ready middleware. These guidelines are fundamentally independent of programming language. They are based on experience, but proper credit must be given to More Effective C++, by Scott Meyers, for opening the eyes of the innocent(?) many years ago. Finally, these are guidelines. There will always be exceptions to these guidelines, in which case all that can be asked (as per these guidelines) is that they be logged in the form of comments in the code.
Compile and RunThe xml-axis/java/build.xml file is the primary 'make' file used by ant to build the application and run the tests. The build.xml file defines ant build targets. Read the build.xml file for more information. Here are some of the useful targets:
To compile the source code: cd xml-axis/java ant compile To run the tests: cd xml-axis/java ant functional-tests Note: these tests start a server on port 8080. If this clashes with the port used by your web application server (such as Tomcat), you'll need to change one of the ports or stop your web application server when running the tests. Please run ant functional-tests and ant all-tests before checking in new code. InternationalizationIf you make changes to the source code that results in the generation of text (error messages or debug information), you must follow the following guidelines to ensure that your text is properly translated. Developer Guidelines
ExampleConsider the following statement:
if ( operationName == null )
We will add an entry into org/apache/axis/i18n/resource.properties: noOperation=No operation name specified. And change the code to read:
if ( operationName == null )
InterfaceAxis uses the standard Java internationalization class java.util.ResourceBundle to access property files and message strings, and uses java.text.MessageFormat to format the strings using variables. Axis provides a single class org.apache.axis.i18n.Messages that manages both ResourceBundle and MessageFormat classes. Messages methods are: public static java.util.ResourceBundle getResourceBundle(); public static String getMessage(String key) throws java.util.MissingResourceException; public static String getMessage(String key, String var) throws java.util.MissingResourceException; public static String getMessage(String key, String var1, String var2) throws java.util.MissingResourceException; public static String getMessage(String key, String[] vars) throws java.util.MissingResourceException; Axis programmers can work with the resource bundle directly via a call to Messages.getResourceBundle(), but the getMessage() methods should be used instead for two reasons:
The getMessage methodsIf you have a message with no variables myMsg00=This is a string.then simply call Messages.getMessage("myMsg00");
then call: Messages.getMessage("myMsg00","name", "Russell");and the resulting string will be: "My name is Russell." You could also call the String array version of getMessage: Messages.getMessage("myMsg00", new String[] {"name", "Russell"});
Note that the getMessage methods throw MissingResourceException if the resource cannot be found. And ParseException if there are more {X} entries than arguments. These exceptions are RuntimeException's, so the caller doesn't have to explicitly catch them. The resource bundle properties file is org/apache/axis/i18n/resource.properties. Extending Message FilesGenerally, within Axis all messages are placed in org.apache.axis.i18n.resource.properties. There are facilities for extending the messages without modifying this file for integration or 3rd party extensions to Axis. See the Integration Guide for details. Creating a WSDL TestHere are the steps that I used to create the sequence test, which generates code from a wsdl file and runs a sequence validation test:
Using tcpmon to Monitor Functional Tests.Here is an easy way to monitor the messages while running functional-tests (or all-tests). java org.apache.axis.utils.tcpmon 8080 localhost 8011 Run your tests, but use the forwarded port for the SimpleAxisServer, and indicate that functional-tests should continue if a failure occurs. ant functional-tests -Dtest.functional.SimpleAxisPort=8011 -Dtest.functional.fail=no The SOAP messages for all of the tests should appear in the tcpmon window. tcpmon is described in more detail in the Axis User's Guide. Using SOAP Monitor to Monitor Functional Tests.If you are debugging code that is running as a web application using a web application server (such as Tomcat) then you may also use the SOAP Monitor utility to view the SOAP request and response messages. http://localhost:<port>/axis/SOAPMonitor As you run your tests, the SOAP messages should appear in the SOAP monitor window. SOAP Monitor is described in more detail in the Axis User's Guide. Running a Single Functional TestIn one window start the server: java org.apache.axis.transport.http.SimpleAxisServer -p 8080 In another window, first deploy the service you're testing: java org.apache.axis.client.AdminClient deploy.wsdd Then bring up the JUnit user interface with your test. For example, to run the the multithread test case: java junit.swingui.TestRunner -noloading test.wsdl.multithread.MultithreadTestCase Turning on Debug OutputThis section is oriented to the Axis default logger: Log4J. For additional information on Log4J, see the section Configuring the Logger.
Writing Temporary OutputRemember that Axis is targeted for use in a number of open-source and other web applications, and so it needs to be a good citizen. Writing output using System.out.println or System.err.println should be avoided. Developers may be tempted to use System.out.println while debugging or analyzing a system. If you choose to do this, you will need to disable the util/TestSrcContent test, which enforces avoidance of System.out.println and System.err.println. It follows that you will need to remove your statements before checking the code back in. As an alternative, we strongly encourage you to take a few moments and introduce debug statements: log.debug("reasonably terse and meaningful message"). If a debug message is useful for understanding a problem now, it may be useful again in the future to you or a peer. Adding TestcasesSee Also: Test and Samples Structure
Editor's Note: We need more effort to streamline and simplify the addition of tests. We also need to think about categorizing tests as the test bucket grows. If you make changes to Axis, please add a test that uses your change. Why?
A good "non-wsdl" test for reference is test/saaj. Test StructureThe Test and Samples Redesign Document is here As of Axis 1.0, RC1, we have moved to a "componentized" test structure. Instead of having one high-level large recursive function, there are smaller, simple "component" build.xml files in the leaf level of the test/** and samples/** trees. These "component" files have a common layout. Their primary targets are:
A "sample" test xml file can be found in test/templateTest Adding Source Code ChecksThe Axis build performs certain automated checks of the files in the source directory (java/src) to make sure certain conventions are followed such as using internationalised strings when issuing messages. If a convention can be reduced to a regular expression match, it can be enforced at build time by updating java/test/utils/TestSrcContent.java. All that is necessary is to add a pattern to the static FileNameContentPattern array. Each pattern has three parameters:
A reasonable summary of the regular expression notation is provided in the Jakarta ORO javadocs. JUnit and AxisYou try to run some JUnit tests on an Axis client that invokes a web service, and you always get this exception: java.lang.ExceptionInInitializerError at org.apache.axis.client.Service.<init>(Service.java:108) ... Caused by: org.apache.commons.logging.LogConfigurationException: ... org.apache.commons.logging.impl.Jdk14Logger does not implement Log at org.apache.commons.logging.impl.LogFactoryImpl.newInstance (LogFactoryImpl.java:555) ... Actually, the Jdk14Logger does implement Log. What you have is a JUnit classloading issue. JUnit's graphical TestRunner has a feature where it will dynamically reload modified classes every time the user presses the "Run" button. This way, the user doesn't need to relaunch the TestRunner after every edit. For this, JUnit uses its own classloader, junit.runner.TestCaseClassLoader. As of JUnit 3.8.1, confusion can arise between TestCaseClassLoader and the system class loader as to which loader did or should load which classes. There are two ways to avoid this problem.
Copy this file, preserving the directory path, into another location, e.g. deployDir. So the copied properties file's path will be deployDir/junit/runner/excluded.properties. Add an extra entry to the end of this file: excluded.9=org.apache.* Edit your classpath so that deployDir appears before junit.jar. This way, the modified excluded.properties will be used, rather than the default. (Don't add the path to excluded.properties itself to the classpath.) This fix will prevent the commons-logging exception. However, other classloading problems might still arise. For example: Dec 10, 2002 7:16:16 PM org.apache.axis.encoding.ser.BeanPropertyTarget set SEVERE: Could not convert [Lfoo.bar.Child; to bean field 'childrenAsArray', type [Lfoo.bar.Child; Dec 10, 2002 7:16:16 PM org.apache.axis.client.Call invoke SEVERE: Exception: java.lang.IllegalArgumentException: argument type mismatch at org.apache.axis.encoding.ser.BeanPropertyTarget.set (BeanPropertyTarget.java:182) at org.apache.axis.encoding.DeserializerImpl.valueComplete (DeserializerImpl.java:284) ... In this case, you have no choice but to give up on dynamic class reloading and use the -noloading argument. One other heads-up about JUnit testing of an Axis web service. Suppose you have run JUnit tests locally on the component that you want to expose as a web service. You press the "Run" button to initiate a series of tests. Between each test, all your data structures are re-initialized. Your tests produce a long green bar. Good. Suppose you now want to run JUnit tests on an Axis client that is connecting to an application server running the Axis web application and with it your web service. Between each test, JUnit will automatically re-initialize your client. Your server-side data structures are a different matter. If you're checking your server data at the end of each test (as you should be) and you run more than one test at a time, the second and later tests will fail because they are generating cumulative data on the Axis server based on preceding tests rather than fresh data based only on the current one. This means that, for each test, you must manually re-initialize your web service. One way to accomplish this is to add to your web service interface a re-initialize operation. Then have the client call that operation at the start of each test. DebuggingRunning the JAX-RPC Compatibility TestsAs well as a specification, JAX-RPC has a Technology Compatibility Kit (TCK) which is available to members of the JAX-RPC Expert Group (and others?). The kit comes as a zip file which you should unzip into a directory of your choosing. The installation instructions are in the JAX-RPC Release Notes document which is stored in the docs directory. If you open the index.html file in the docs directory using a web browser, you'll see a list of all the documents supplied with the kit. Note that the kit includes the JavaTest test harness which is used for running the compatibility tests. If any more information is needed about running these tests, please add it here! Axis System Integration GuideAxis System Integration Guide
1.2 Version
IntroductionThe primary purpose of this guide is to present how Axis can be integrated into an existing web application server, such as Tomcat or WebSphere, for example. Axis has a number of Pluggable APIs that are necessary for such an integration. The reader may find useful background information in the Architecture Guide. Pluggable APIsThe following are the points that are pluggable in order to integrate Axis into a web application server. The first subsection details a number of pluggable components in general. More details are provided for other components in the remaining subsections. ComponentsThis section describes in general how to plug specializations of various components into Axis. General StrategyTo override the default behavior for a pluggable component:
Example 1To override the default behavior for the Java Compiler:
Example 2To override the default behavior for the SocketFactory in an environment that does not allow resources to be located/loaded appropriately, or where the behavior needs to be forced to a specific implementation:
Reference(Component/Package: org.apache.axis.components.*)
Logging/TracingAxis logging and tracing is based on the Logging component of the Jakarta Commons project, or the Jakarta Commons Logging (JCL) SPI. The JCL provides a Log interface with thin-wrapper implementations for other logging tools, including Log4J, Avalon LogKit, and JDK 1.4. The interface maps closely to Log4J and LogKit. Justification/RationaleA pluggable logging/trace facility enables Axis to direct logging/trace messages to a host web application server's logging facility. A central logging facility with a single point of configuration/control is superior to distinct logging mechanisms for each of a multitude of middleware components that are to be integrated into a web application server. IntegrationThe minimum requirement to integrate with another logger is to provide an implementation of the org.apache.commons.logging.Log interface. In addition, an implementation of the org.apache.commons.logging.LogFactory interface can be provided to meet specific requirements for connecting to, or instantiating, a logger.
Mechanism
Logger Configuration
Configuration
The EngineConfiguration is provided by an implementation of the interface org.apache.axis.EngineConfigurationFactory, which currently provides methods that return client and server configurations. Our focus will be how to define the implementation class for EngineConfigurationFactory.
HandlersSee the Architecture Guide for current information on Handlers. InternationalizationAxis supports internationalization by providing both a property file of the strings used in Axis, and an extension mechanism that facilitates accessing internal Axis messages and extending the messages available to integration code based on existing Axis code. Translation
Extending Message FilesAxis provides a Message file extension mechanism that allows Axis-based code to use Axis message keys, as well as new message keys unique to the extended code.
Performance MonitoringAxis does not yet include specific Performance Monitoring Plugs. EncodingAxis does not yet include an Encoding Plug. WSDL Parser and Code Generator FrameworkWSDL2Java is Axis's tool to generate Java artifacts from WSDL. This tool is extensible. If users of Axis wish to extend Axis, then they may also need to extend or change the generated artifacts. For example, if Axis is inserted into some product which has an existing deployment model that's different than Axis's deployment model, then that product's version of WSDL2Java will be required to generate deployment descriptors other than Axis's deploy.wsdd. What follows immediately is a description of the framework. If you would rather dive down into the dirt of examples, you could learn a good deal just from them. Then you could come back up here and learn the gory details. There are three parts to WSDL2Java:
Symbol TableThe symbol table, found in org.apache.axis.wsdl.symbolTable, will contain all the symbols from a WSDL document, both the symbols from the WSDL constructs themselves (portType, binding, etc), and also the XML schema types that the WSDL refers to. NOTE: Needs lots of description here. The symbol table is not extensible, but you can add fields to it by using the Dynamic Variables construct:
Parser Front End and Generator FrameworkThe parser front end and generator framework is located in org.apache.axis.wsdl.gen. The parser front end consists of two files:
Code Generator Back EndThe meat of the WSDL2Java back end generators is in org.apache.axis.wsdl.toJava. Emitter extends Parser. org.apache.axis.wsdl.WSDL2Java extends WSDL2. JavaGeneratorFactory implements GeneratorFactory. And the various JavaXXXWriter classes implement the Generator interface. NOTE: Need lots more description here... WSDL Framework Extension ExamplesEverything above sounds rather complex. It is, but that doesn't mean your extension has to be. Example 1 - Simple extension of WSDL2Java - additional artifactThe simplest extension of the framework is one which generates everything that WSDL2Java already generates, plus something new. Example 1 is such an extension. It's extra artifact is a file for each service that lists that service's ports. I don't know why you'd want to do this, but it makes for a good, simple example. See samples/integrationGuide/example1 for the complete implementation of this example.
Example 2 - Not quite as simple an extension of WSDL2Java - change an artifactIn this example, we'll replace deploy.wsdd with mydeploy.useless. For brevity, mydeploy.useless is rather useless. Making it useful is an exercise left to the reader. See samples/integrationGuide/example2 for the complete implementation of this example.
Client SSLThe default pluggable secure socket factory module (see Pluggable APIs) uses JSSE security. Review the JSSE documentation for details on installing, registering, and configuring JSSE for your runtime environment. Axis Architecture GuideAxis Architecture Guide
IntroductionThis guide records some of the rationale of the architecture and design of Axis. Architectural OverviewAxis consists of several subsystems working together, as we shall see later. In this section we'll give you an overview of how the core of Axis works. Handlers and the Message Path in AxisPut simply, Axis is all about processing Messages. When the central Axis processing logic runs, a series of Handlers are each invoked in order. The particular order is determined by two factors - deployment configuration and whether the engine is a client or a server. The object which is passed to each Handler invocation is a MessageContext. A MessageContext is a structure which contains several important parts: 1) a "request" message, 2) a "response" message, and 3) a bag of properties. More on this in a bit. There are two basic ways in which Axis is invoked:
In either case, the Axis framework's job is simply to pass the resulting MessageContext through the configured set of Handlers, each of which has an opportunity to do whatever it is designed to do with the MessageContext. Message Path on the ServerThe server side message path is shown in the following diagram. The small cylinders represent Handlers and the larger, enclosing cylinders represent Chains (ordered collections of Handlers which will be described shortly). The AxisEngine's first job is to look up the transport by name. The transport is an object which contains a request Chain, a response Chain, or perhaps both. A Chain is a Handler consisting of a sequence of Handlers which are invoked in turn -- more on Chains later. If a transport request Chain exists, it will be invoked, passing the MessageContext into the invoke() method. This will result in calling all the Handlers specified in the request Chain configuration. After the transport request Handler, the engine locates a global request Chain, if configured, and then invokes any Handlers specified therein. At some point during the processing up until now, some Handler has hopefully set the serviceHandler field of the MessageContext (this is usually done in the HTTP transport by the "URLMapper" Handler, which maps a URL like "http://localhost/axis/services/AdminService" to the "AdminService" service). This field determines the Handler we'll invoke to execute service-specific functionality, such as making an RPC call on a back-end object. Services in Axis are typically instances of the "SOAPService" class (org.apache.axis.handlers.soap.SOAPService), which may contain request and response Chains (similar to what we saw at the transport and global levels), and must contain a provider, which is simply a Handler responsible for implementing the actual back end logic of the service. For RPC-style requests, the provider is the org.apache.axis.providers.java.RPCProvider class. This is just another Handler that, when invoked, attempts to call a backend Java object whose class is determined by the "className" parameter specified at deployment time. It uses the SOAP RPC convention for determining the method to call, and makes sure the types of the incoming XML-encoded arguments match the types of the required parameters of the resulting method. The Message Path on the ClientThe Message Path on the client side is similar to that on the server side, except the order of scoping is reversed, as shown below. After the service request Chain, the global request Chain, if any, is invoked, followed by the transport. The Transport Sender, a special Handler whose job it is to actually perform whatever protocol-specific operations are necessary to get the message to and from the target SOAP server, is invoked to send the message. The response (if any) is placed into the responseMessage field of the MessageContext, and the MessageContext then propagates through the response Chains - first the transport, then the global, and finally the service. SubsystemsAxis comprises several subsystems working together with the aim of separating responsibilities cleanly and making Axis modular. Subsystems which are properly layered enable parts of a system to be used without having to use the whole of it (or hack the code). The following diagram shows the layering of subsystems. The lower layers are independent of the higher layers. The 'stacked' boxes represent mutually independent, although not necessary mutually exclusive, alternatives. For example, the HTTP, SMTP, and JMS transports are independent of each other but may be used together.
In fact, the Axis source code is not as cleanly separated into subsystems as the above diagram might imply. Some subsystems are spread over several packages and some packages overlap more than one subsystem. Proposals to improve the code structure and make it conform more accurately to the notional Axis subsystems will be considered when we get a chance. Message Flow SubsystemHandlers and ChainsHandlers are invoked in sequence to process messages. At some point in the sequence a Handler may send a request and receive a response or else process a request and produce a response. Such a Handler is known as the pivot point of the sequence. As described above, Handlers are either transport-specific, service-specific, or global. The Handlers of each of these three different kinds are combined together into Chains. So the overall sequence of Handlers comprises three Chains: transport, global, and service. The following diagram shows two sequences of handlers: the client-side sequence on the left and the server-side sequence on the right. A web service does not necessarily send a response message to each request message, although many do. However, response Handlers are still useful in the message path even when there isn't a response message, e.g. to stop timers, clean up resources, etc. A Chain is a composite Handler, i.e. it aggregates a collection of Handlers as well as implementing the Handler interface as shown in the following UML diagram: A Chain also has similarities to the Chain of Responsibility design pattern in which a request flows along a sequence of Handlers until it is processed. Although an Axis Chain may process a request in stages over a succession of Handlers, it has the same advantages as Chain of Responsibility: flexibility and the ease with which new function can be added. Back to message processing -- a message is processed by passing through the appropriate Chains. A message context is used to pass the message and associated environment through the sequence of Handlers. The model is that Axis Chains are constructed offline by having Handlers added to them one at a time. Then they are turned online and message contexts start to flow through the Chains. Multiple message contexts may flow through a single Chain concurrently. Handlers are never added to a Chain once it goes online. If a Handler needs to be added or removed, the Chain must be 'cloned', the modifications made to the clone, and then the clone made online and the old Chain retired when it is no longer in use. Message contexts that were using the old Chain continue to use it until they are finished. This means that Chains do not need to cope with the addition and removal of Handlers while the Chains are processing message contexts -- an important simplification. The deployment registry has factories for Handlers and Chains. Handlers and Chains can be defined to have 'per-access', 'per-request', or 'singleton' scope although the registry currently only distinguishes between these by constructing non-singleton scope objects when requested and constructing singleton scope objects once and holding on to them for use on subsequent creation requests. Targeted ChainsA Targeted Chain is a special kind of chain which may have any or all of: a request Handler, a pivot Handler, and a response Handler. The following class diagram shows how Targeted Chains relate to Chains. Note that a Targeted Chain is an aggregation of Handlers by virtue of extending the Chain interface which is an aggregation of Handlers.
A service is a special kind of Targeted Chain in which the pivot Handler is known as a "provider". Fault ProcessingNow let's consider what happens when a fault occurs. The Handlers prior to the Handler that raised the fault are driven, in reverse order, for onFault (previously misnamed 'undo'). The scope of this backwards scan is interesting: all Handlers previously invoked for the current Message Context are driven. Need to explain how "FaultableHandlers" and "WSDD Fault Flows" fit in. Message ContextsThe current structure of a MessageContext is shown below. Each message context may be associated with a request Message and/or a response Message. Each Message has a SOAPPart and an Attachments object, both of which implement the Part interface. EngineAxis has an abstract AxisEngine class with two concrete subclasses: AxisClient drives the client side handler chains and AxisServer drives the server side handler chains. The relationships between these classes is fairly simple: Engine ConfigurationThe EngineConfiguration interface is the means of configuring the Handler factories and global options of an engine instance. An instance of a concrete implementation of EngineConfiguration must be passed to the engine when it is created and the engine must be notified if the EngineConfiguration contents are modified. The engine keeps a reference to the EngineConfiguration and then uses it to obtain Handler factories and global options. The EngineConfiguration interface belongs to the Message Flow subsystem which means that the Message Flow subsystem does not depend on the Administration subsystem. Administration SubsystemThe Administration subsystem provides a way of configuring Axis engines. The configuration information an engine needs is a collection of factories for runtime artefacts such as Chains and SOAPServices and a set of global configuration options for the engine. The Message Flow subsystem's EngineConfiguration interface is implemented by the Administration subsystem. FileProvider enables an engine to be configured statically from a file containing a deployment descriptor which is understood by the WSDDDeployment class. SimpleProvider, on the other hand, enables an engine to be configured dynamically. WSDD-Based AdministrationWSDD is an XML grammer for deployment descriptors which are used to statically configure Axis engines. Each Handler needs configuration in terms of the concrete class name of a factory for the Handler, a set of options for the handler, and a lifecycle scope value which determines the scope of sharing of instances of the Handler. The structure of the WSDD grammar is mirrored by a class hierarchy of factories for runtime artefacts. The following diagram shows the classes and the types of runtime artefacts they produce (a dotted arrow means "instantiates"). Message Model SubsystemSOAP Message ModelThe XML syntax of a SOAP message is fairly simple. A SOAP message consists of an envelope containing:
The only body entry defined by SOAP is a SOAP fault which is used for reporting errors. Some of the XML elements of a SOAP message define namespaces, each in terms of a URI and a local name, and encoding styles, a standard one of which is defined by SOAP. Header entries may be tagged with the following optional SOAP attributes:
So the SOAP message model looks like this: Message ElementsThe classes which represent SOAP messages form a class hierarchy based on the MessageElement class which takes care of namespaces and encodings. The SOAPHeaderElement class looks after the actor and mustUnderstand attributes. DeserializationThe class mainly responsible for XML parsing, i.e. deserialization, is DeserializationContext ('DC'). DC manages the construction of the parse tree and maintains a stack of SAX handlers, a reference to the MessageElement that is currently being deserialized, a stack of namespace mappings, a mapping from IDs to elements, a set of type mappings for deserialization (see Encoding Subsystem) and a SAX event recorder. Elements that we scan over, or ones for which we don't have a particular deserializer, are recorded - in other words, the SAX events are placed into a queue which may be 'played back' at a later time to any SAX ContentHandler. Once a SOAPEnvelope has been built, either through a parse or manual construction by the user, it may be output using a SerializationContext (also see Encoding Subsystem). MessageElements all have an output() method which lets them write out their contents. The SAX handlers form a class hierarchy: and stack up as shown in the following diagram: Initially, the SAX handler stack just contains an instance of EnvelopeHandler which represents the fact that parsing of the SOAP envelope has not yet started. The EnvelopeHandler is constructed with a reference to an EnvelopeBuilder, which is the SAX handler responsible for parsing the SOAP envelope. During parsing, DC receives the events from the SAX parser and notifies either the SAX handler on the top of its handler stack, the SAX event recorder, or both. On the start of an element, DC calls the SAX handler on the top of its handler stack for onStartChild. This method returns a SAX handler to be used to parse the child, which DC pushes on its SAX handler stack and calls for startElement. startElement, amongst other things, typically creates a new MessageElement of the appropriate class and calls DC for pushNewElement. The latter action creates the parent-child relationships of the parse tree. On the end of an element, DC pops the top SAX handler from its handler stack and calls it for endElement. It then drives SAX handler which is now on the top of the handler stack for onEndChild. Finally, it sets the MessageElement that is currently being deserialized to the parent of the current one. Elements which are not defined by SOAP are treated using a SOAPHandler as a SAX event handler and a MessageElement as a node in the parse tree. Encoding SubsystemEncoding is most easily understood from the bottom up. The basic requirement is to transform between values of programming language datatypes and their XML representations. In Axis, this means encoding (or 'serializing') Java objects and primitives into XML and decoding (or 'deserializing') XML into Java objects and primitives. The basic classes that implement these steps are serializers and deserializers. Particular serializers and deserializers are written to support a specific XML processing mechanism such as DOM or SAX. So serializer factories and deserializer factories are introduced to construct serializers and deserializers for a XML processing mechanism which is specified as a parameter. As is apparent from the above class diagrams, each pair of Java type and XML data type which needs encoding and decoding requires specific serializers and deserializers (actually one of each per XML processing mechanism). So we need to maintain a mapping from a pair of Java type and XML data type, identified by a QName, to a serializer factory and a deserializer factory. Such a mapping is known as a type mapping. The type mapping class hierarchy is shown below. Notice how the default type mapping instantiates the various serializer and deserialiser factories. There is one final level of indirection. How do we know which type mapping to use for a particular message? This is determined by the encoding which is specified in the message. A type mapping registry maintains a map from encoding name (URI) to type mapping. Note that the XML data type QNames are defined by the encoding. So, in summary, to encode a Java object or primitive data value to a XML datatype or to decode the latter to the former, we need to know:
WSDL Tools SubsystemThe WSDL Tools subsystem contains WSDL2Java and Java2WSDL. The Axis runtime does not depend on these tools -- they are just there to make life easier for the user. WSDL2JavaThis tool takes a description of a web service written in WSDL and emits Java artefacts used to access the web service. There are three layers inside the tool:
Java2WSDLtbd. Interaction DiagramsClient Side ProcessingThe client side Axis processing constructs a Call object with associated Service, MessageContext, and request Message as shown below before invoking the AxisClient engine.
Pluggable-Component DiscoveryWhile most pluggable components infrastructures (jaxp/xerces, commons-logging, etc) provide discovery features, it is foreseen that there are situations where these may evolve over time. For example, as leading-edge technologies are reworked and adopted as standards, discovery mechanisms are likely to change. Therefore, component discovery must be relegated to a single point of control within AXIS, typically an AXIS-specific factory method. These factory methods should conform to current standards, when available. As technologies evolve and/or are standardized, the factory methods should be kept up-to-date with appropriate discovery mechanisms. Open Issues
Axis Reference GuideAxis Reference Guide
1.2 Version
Tools ReferenceWSDL2Java ReferenceUsage: java org.apache.axis.wsdl.WSDL2Java [options] WSDL-URI -h, --helpPrint the usage statement and exit -v, --verboseSee what the tool is generating as it is generating it. -n, --noImportsOnly generate code for the WSDL document that appears on the command line. The default behaviour is to generate files for all WSDL documents, the immediate one and all imported ones. -O, --timeoutTimeout in seconds. The default is 45. Use -1 to disable the timeout. -D, --DebugPrint debug information, which currently is WSDL2Java's symbol table. Note that this is only printed after the symbol table is complete, ie., after the WSDL is parsed successfully. -W, --noWrappedThis turns off the special treatment of what is called "wrapped" document/literal style operations. By default, WSDL2Java will recognize the following conditions:
When it sees this, WSDL2Java will 'unwrap' the top level element, and treat each of the components of the element as arguments to the operation. This type of WSDL is the default for Microsoft .NET web services, which wrap up RPC style arguments in this top level schema element. -s, --server-sideEmit the server-side bindings for the web service:
-S, --skeletonDeploy <argument>Deploy either the skeleton (true) or the implementation (false) in deploy.wsdd. In other words, for "true" the service clause in the deploy.wsdd file will look something like: <service name="AddressBook" provider="java:RPC"> <parameter name="className" value="samples.addr.AddressBookSOAPBindingSkeleton"/> ... </service> and for "false" it would look like: <service name="AddressBook" provider="java:RPC"> <parameter name="className" value="samples.addr.AddressBookSOAPBindingImpl"/> ... </service> The default for this option is false. When you use this option, the --server-side option is assumed, so you don't have to explicitly specify --server-side as well. -N, --NStoPkg <argument>=<value>By default, package names are generated from the namespace strings in the WSDL document in a magical manner (typically, if the namespace is of the form "http://x.y.com" or "urn:x.y.com" the corresponding package will be "com.y.x"). If this magic is not what you want, you can provide your own mapping using the --NStoPkg argument, which can be repeated as often as necessary, once for each unique namespace mapping. For example, if there is a namespace in the WSDL document called "urn:AddressFetcher2", and you want files generated from the objects within this namespace to reside in the package samples.addr, you would provide the following option to WSDL2Java: --NStoPkg urn:AddressFetcher2=samples.addr
(Note that if you use the short option tag, "-N", then there must not be a space between "-N" and the namespace.) -f, --fileNStoPkg <argument>If there are a number of namespaces in the WSDL document, listing a mapping for them all could become tedious. To help keep the command line terse, WSDL2Java will also look for mappings in a properties file. By default, this file is named "NStoPkg.properties" and it must reside in the default package (ie., no package). But you can explicitly provide your own file using the --fileNStoPkg option. The entries in this file are of the same form as the arguments to the --NStoPkg command line option. For example, instead of providing the command line option as above, we could provide the same information in NStoPkg.properties: urn\:AddressFetcher2=samples.addr (Note that the colon must be escaped in the properties file.) If an entry for a given mapping exists both on the command line and in the properties file, the command line entry takes precedence. -p, --package <argument>This is a shorthand option to map all namespaces in a WSDL document to the same Java package name. This can be useful, but dangerous. You must make sure that you understand the effects of doing this. For instance there may be multiple types with the same name in different namespaces. It is an error to use the --NStoPkg switch and --package at the same time. -o, --output <argument>The root directory for all emitted files. -d, --deployScope <argument>Add scope to deploy.wsdd: "Application", "Request", or "Session". If this option does not appear, no scope tag appears in deploy.wsdd, which the Axis runtime defaults to "Request". -t, --testCaseGenerate a client-side JUnit test case. This test case can stand on its own, but it doesn't really do anything except pass default values (null for objects, 0 or false for primitive types). Like the generated implementation file, the generated test case file could be considered a template that you may fill in. -a, --allGenerate code for all elements, even unreferenced ones. By default, WSDL2Java only generates code for those elements in the WSDL file that are referenced. A note about what it means to be referenced. We cannot simply say: start with the services, generate all bindings referenced by the service, generate all portTypes referenced by the referenced bindings, etc. What if we're generating code from a WSDL file that only contains portTypes, messages, and types? If WSDL2Java used service as an anchor, and there's no service in the file, then nothing will be generated. So the anchor is the lowest element that exists in the WSDL file in the order:
For example, if a WSDL file only contained types, then all the listed types would be generated. But if a WSDL file contained types and a portType, then that portType will be generated and only those types that are referenced by that portType. Note that the anchor is searched for in the WSDL file appearing on the command line, not in imported WSDL files. This allows one WSDL file to import constructs defined in another WSDL file without the nuisance of having all the imported WSDL file's constructs generated. -T, --typeMappingVersion <argument>Indicate 1.1 or 1.2. The default is 1.2 (SOAP 1.2 JAX-RPC compliant). -F, --factory <argument>Used to extend the functionality of the WSDL2Java emitter. The argument is the name of a class which extends JavaWriterFactory. -H, --helperGenEmits separate Helper classes for meta data. -U, --user <argument>This username is used in resolving the WSDL-URI provided as the input to WSDL2Java. If the URI contains a username, this will override the command line switch. An example of a URL with a username and password is: http://user:password@hostname:port/path/to/service?WSDL -P, --password <argument>
This password is used in resolving the WSDL-URI provided as the input to WSDL2Java. If the URI contains a password, this will override the command line switch. -c, --implementationClassName <argument>Set the name of the implementation class.Especially useful when exporting an existing class as a web service using java2wsdl followed by wsdl2java. If you are using the skeleton deploy option you must make sure, after generation, that your implementation class implements the port type name interface generated by wsdl2java. You should also make sure that all your exported methods throws java.lang.RemoteException. Java2WSDL ReferenceHere is the help message generated from the current tool: Java2WSDL emitter Usage: java org.apache.axis.wsdl.Java2WSDL [options] class-of-portType Options: -h, --help print this message and exit -I, --input <argument> input WSDL filename -o, --output <argument> output WSDL filename -l, --location <argument> service location url -P, --portTypeName <argument> portType name (obtained from class-of-portType if not specified) -b, --bindingName <argument> binding name (--servicePortName value + "SOAPBinding" if not specified) -S, --serviceElementName <argument> service element name (defaults to --servicePortName value + "Service") -s, --servicePortName <argument> service port name (obtained from --location if not specified) -n, --namespace <argument> target namespace -p, --PkgtoNS <argument>=<value> package=namespace, name value pairs -m, --methods <argument> space or comma separated list of methods to export -a, --all look for allowed methods in inherited class -w, --outputWsdlMode <argument> output WSDL mode: All, Interface, Implementation -L, --locationImport <argument> location of interface wsdl -N, --namespaceImpl <argument> target namespace for implementation wsdl -O, --outputImpl <argument> output Implementation WSDL filename, setting this causes --outputWsdlMode to be ignored -i, --implClass <argument> optional class that contains implementation of methods in class-of-portType. The debug information in the class is used to obtain the method parameter names, which are used to set the WSDL part names. -x, --exclude <argument> space or comma separated list of methods not to export -c, --stopClasses <argument> space or comma separated list of class names which will stop inheritance search if --all switch is given -T, --typeMappingVersion <argument> indicate 1.1 or 1.2. The default is 1.1 (SOAP 1.1 JAX-RPC compliant 1.2 indicates SOAP 1.1 encoded.) -A, --soapAction <argument> value of the operations soapAction field. Values are DEFAULT, OPERATION or NONE. OPERATION forces soapAction to the name of the operation. DEFAULT causes the soapAction to be set according to the operations meta data (usually ""). NONE forces the soapAction to "". The default is DEFAULT. -y, --style <argument> The style of binding in the WSDL, either DOCUMENT, RPC, or WRAPPED. -u, --use <argument> The use of items in the binding, either LITERAL or ENCODED -e, --extraClasses <argument> A space or comma separated list of class names to be added to the type section. -C, --importSchema A file or URL to an XML Schema that should be physically imported into the generated WSDL -X, --classpath additional classpath elements Details: portType element name= <--portTypeName value> OR <class-of-portType name> binding element name= <--bindingName value> OR <--servicePortName value>Soap Binding service element name= <--serviceElementName value> OR <--portTypeName value> Service port element name= <--servicePortName value> address location = <--location value>
-h , --help
-I, --input <WSDL file>
-o, --output <WSDL file>
-l, --location <location>
-P, --portTypeName <name>
-b, --bindingName <name>
-S, --serviceElementName <name>
-s, --servicePortName <name>
-n, --namespace <target namespace>
-p, --PkgToNS <package> <namespace>
-m, --methods <arguments>
-a, --all
-w, --outputWSDLMode <mode>
-L, --locationImport <url>
-N, --namespaceImpl <namespace>
-O, --outputImpl <WSDL file>
-i, --implClass <impl-class>
-x, --exclude <list>
-c, --stopClasses <list>
-T, --typeMappingVersion <version>
-A, --soapAction <argument>
-y, --style <argument>
-u, --use <argument>
-e, --extraClasses <argument>
-C, --importSchema
Deployment (WSDD) ReferenceNote : all the elements referred to in this section are in the WSDD namespace, namely "http://xml.apache.org/axis/wsdd/".
Global Axis ConfigurationThe server is configured (by default) by values in the server-config.wsdd file, though a dedicated Axis user can write their own configuration handler, and so store configuration data in an LDAP server, database, remote web service, etc. Consult the source on details as to how to do that. You can also add options to the web.xml file and have them picked up automatically. We don't encourage that as it is nice to keep configuration stuff in one place. In the server-config file, there is a global configuration section, which supports parameter name/value pairs as nested elements. Here are the options that we currently document, though there may be more (consult the source, as usual). <globalConfiguration> <parameter name="adminPassword" value="admin"/> <parameter name="attachments.Directory" value="c:\temp\attachments"/> <parameter name="sendMultiRefs" value="true"/> <parameter name="sendXsiTypes" value="true"/> <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/> <parameter name="sendXMLDeclaration" value="true"/> <parameter name="enable2DArrayEncoding" value="true"/> </globalConfiguration>
Individual Service ConfigurationTODO Here are some of the per-service configuration options are available; these can be set in the wsdd file used to deploy a service, from where they will be picked up. More may exist.
Axis Logging ConfigurationAxis uses the Jakarta Projects's commons-logging API, as implemented in commons-logging.jar to implement logging throughout the code. Normally this library routes the logging to the Log4j library, provided that an implementation of log4j is on the classpath of the server or client. The commons-logging API can also bind to Avalon, System.out or the Java1.4 logger. The JavaDocs for the library explain the process for selecting a logger, which can be done via a system property or a properties file in the classpath. Log4J can be configured using the file log4j.properties in the classpath; later versions also support an XML configuration. Axis includes a preconfigured log4j.properties file in axis.jar. While this is adequate for basic use, any complex project will want to modify their own version of the file. Here is what to do
Log CategoriesAxis classes that log information create their own per-class log, each of which may output information at different levels. For example, the main entry point servlet has a log called org.apache.axis.transport.http.AxisServlet, the AxisEngine is org.apache.axis.AxisEngine, and so on. There are also special logs for special categories.
Pre-Configured Axis Components ReferenceOn the server:
On the client:
Axis: further readingRecommended ReadingHere are things you can read to understand and use Axis better. Remember, you also have access to all the source if you really want to find out how things work (or why they don't). Axis installation, use and internals
Specifications
Explanations, articles and presentations
Interoperability
Advanced topics
Books
Authors, publishers: we welcome additions to this section of any books which have some explicit coverage of Axis. Free paper/pdf copies and other forms of bribery accepted. External Sites covering Web Services
Axis requirements & statusRequirementsThere is a non-requirements section below.
Non-requirements (won't be supported)
Releases and test cyclesWe're planning on releasing alpha1 (a1), alpha2 (a2), beta, and 3.0. Axis (C++)Axis C++ 1.5 Final is Available!Axis C++ 1.5 FinalKey features of Axis C++ 1.5 Final
New client side transport
The Bug FixesAXISCPP-605 Known IssuesGNU make based build system is not working. We hope you will enjoy using Axis C++. Please report any bugs in Jira and feel free to let us know your thoughts and/or problems in axis-c-user@ws.apache.org
Axis C++ DocumentationDocumentationApache Axis C++ 1.5 Final Installation GuidesUser GuidesDeveloper GuidesReference MaterialAxis C++ download pageDownload Axis C++(Direct link to a Axis C++ distribution folder) (Click on the address of a mirror. Once you are presented with the contents of the dist folder, click on the "ws" folder. The Axis C++ teamThe Axis C++ teamActive ContributorsSusantha Kumara <susantha@virtusa.com, susantha@opensource.lk>, Damitha Kumarage <damitha@beyondm.net, damitha@opensource.lk>, Roshan Weerasuriya <roshan@jkcsworld.com, roshan@opensource.lk>, Sanjaya Singharage <sanjayas@jkcsworld.com,sanjayas@opensource.lk>, John Hawkins <HAWKINSJ@uk.ibm.com>, Samisa Abeysinghe <samisa_abeysinghe@yahoo.com>, Fred Preston <PRESTONF@uk.ibm.com>, Mark Whitlock <mark_whitlock@uk.ibm.com>, Andrew Perry <PERRYAN@uk.ibm.com>, Adrian Dick <adrian.dick@uk.ibm.com>, Sanjiva Weerawarana <sanjiva@opensource.lk>, Farhaan Mohideen <farhaan@opensource.lk>, Nithyakala Thangarajah <nithya@opensource.lk>, Rangika Mendis <rangika@opensource.lk>, Sharanka Perera <sharanka@opensource.lk>, M.F.Rinzad Ahamed <rinzad@opensource.lk>, Additional ContributorsChaminda Divitotawela <cdivitotawela@virtusa.com, chadiv@opensource.lk>, Nuwan Gurusinghe <nuwan@beyondm.net, nuwan@opensource.lk>, Chamindra de Silva <chamindra@virtusa.com>, Kanchana Welagedara <kanchana@opensource.lk>, Srinath Perera <hemapani@cse.mrt.ac.lk, hemapani@opensource.lk>, Thushantha Ravipriya De Alwis <thushantha@beyondm.net, ravi@opensource.lk>, Dimuthu Leelarathne <muthulee@cse.mrt.ac.lk, muthulee@opensource.lk>, Jeyakumaran.C <jkumaran@opensource.lk>, Vairamuthu Thayapavan <vtpavan@opensource.lk>, Satheesh Thurairajah Piranavam ThiruChelvan <chelvan@opensource.lk>, Dharmarajeswaran Dharmeehan <dhar@opensource.lk>, Selvarajah Selvendra <selva@opensource.lk>, Lilantha Darshana <Lilantha@virtusa.com>, Nadika Ranasinghe <nranasinghe@virtusa.com, nadika@opensource.lk>, DownloadsWebServices - AxisWebServices - Axis - Releases
For nightly builds, see the Interim Drops page. WebServices - AxisWebServices - Axis - Interim
Nightly builds are done of the current source in the
CVS repository. The source and binaries from these builds are available at:
http://cvs.apache.org/dist/axis/nightly
Nightly Snapshots of the current CVS source tree are available at:
http://cvs.apache.org/snapshots/ws-axis/ TranslationRelated ProjectsMiscWebServices - AxisWebServices - Axis - Who We AreThe Axis Project operates on a meritocracy: the more you do, the more responsibility you will obtain. This page lists all of the people who have gone the extra mile and are Committers. If you would like to get involved, the first step is to join the mailing lists. We ask that you please do not send us emails privately asking for support. We are non-paid volunteers who help out with the project and we do not necessarily have the time or energy to help people on an individual basis. Instead, we have setup mailing lists which often contain hundreds of individuals who will help answer detailed requests for help. The benefit of using mailing lists over private communication is that it is a shared resource where others can also learn from common mistakes and as a community we all grow together. Active Committers (Java)
Active Committers (C++)
Committers Emeriti (committers that have been inactive for 3 months or more)
WebServices - AxisWebServices - Axis - Contact Us
If you have questions or comments about this site, please send email
to: If you have questions or comments about the software or documentations on this site, please subscribe to the axis-user mailing list: The Axis project is an effort of the Apache Software Foundation. The address for general ASF correspondence and licensing questions is: You can find more contact information for the Apache Software Foundation on the contact page of the main Apache site. WebServices - AxisWebServices - Axis - Legal StuffAll material on this website is Copyright © 1999-2003, The Apache Software Foundation. Sun, Sun Microsystems, Solaris, Java, JavaServer Web Development Kit, and JavaServer Pages are trademarks or registered trademarks of Sun Microsystems, Inc. UNIX is a registered trademark in the United States and other countries, exclusively licensed through X/Open Company, Ltd. Windows, WindowsNT, and Win32 are registered trademarks of Microsoft Corp. All other product names mentioned herein and throughout the entire web site are trademarks of their respective owners. WebServices - AxisWebServices - Axis - Misc NotesMisc notes and docs that might be of interest...
|