Official Documentation (ws Apache Org) - Axis2 - Part 1

  • Uploaded by: Fede
  • 0
  • 0
  • October 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Official Documentation (ws Apache Org) - Axis2 - Part 1 as PDF for free.

More details

  • Words: 49,159
  • Pages: 200
AXIS 2 Índice de contenido AXIS 2..................................................................................................................................................1 Introduction..........................................................................................................................................7 Apache Axis2 User's Guide.............................................................................................................8 How To.............................................................................................................................................8 Data Bindings:.............................................................................................................................9 Transports:...................................................................................................................................9 Axis2 Tools:................................................................................................................................9 Apache Axis2 Developers..............................................................................................................10 References......................................................................................................................................11 Apache Axis2 Installation Guide........................................................................................................11 Contents.........................................................................................................................................11 Axis2 Distributions........................................................................................................................11 1. Standard Binary Distribution................................................................................................11 2. WAR (Web Archive) Distribution.........................................................................................12 3. Documents Distribution........................................................................................................12 4. Source Distribution...............................................................................................................12 System Requirements....................................................................................................................12 Install Axis2 as a Standalone Server using Standard Binary Distribution.....................................12 1. Download and Install the Apache Axis2 Binary Distribution...............................................12 2. Starting up Axis2 Standalone Server....................................................................................13 3. Building the Axis2 Web Application (axis2.war) Using Standard Binary Distribution........13 4. Getting Familiar with the Axis2 Convenient Scripts............................................................13 Install Axis2 in a Servlet Container...............................................................................................14 Uploading Services........................................................................................................................19 Advanced.......................................................................................................................................23 Axis2 Source Distribution.........................................................................................................23 Setting Up the Environment and Tools................................................................................23 Building Binaries and the WAR File Using the Source Distribution...................................24 Apache Axis2 Modules.......................................................................................................................24 Application Server Specific Configuration Guide.............................................................................25 WebLogic/ WebSphere..................................................................................................................25 1. Use exploded configuration to deploy Axis2 WAR..............................................................25 2. Lack of namespacing on serialised items..............................................................................26 Axis2 Quick Start Guide....................................................................................................................26 Content...........................................................................................................................................26 A Quick Setup Note:......................................................................................................................27 Introduction....................................................................................................................................27 Getting Ready................................................................................................................................33 Axis2 Services...............................................................................................................................34 Creating Services...........................................................................................................................35 Deploying POJOs......................................................................................................................35 Building the Service using AXIOM..........................................................................................37 Generating the Service using ADB...........................................................................................41 Generating the Service using XMLBeans.................................................................................42 Generating the Service using JiBX...........................................................................................44 1

Creating Clients.............................................................................................................................45 Creating a Client with AXIOM.................................................................................................45 Generating a Client using ADB................................................................................................48 Generating a Client using XMLBeans......................................................................................49 Generating a Client using JiBX................................................................................................51 Summary........................................................................................................................................52 For Further Study...........................................................................................................................52 Apache Axis2 User's Guide................................................................................................................53 Content...........................................................................................................................................53 Introducing Axis2..........................................................................................................................53 What is Axis2?..........................................................................................................................53 What's Under the Hood?...........................................................................................................54 How Axis2 Handles SOAP Messages.......................................................................................54 Axis2 Distributions...................................................................................................................55 The Axis2 Standard Binary Distribution..............................................................................55 axis2.war Distribution Directory Hierarchy.........................................................................56 Axis2 Documentation Distribution Directory Hierarchy.....................................................57 Axis2 and Clients.................................................................................................................58 Installing and Testing Client Code.................................................................................................58 Introduction to Services.................................................................................................................59 Message Exchange Patterns......................................................................................................59 Creating Clients.............................................................................................................................60 Choosing a Client Generation Method......................................................................................60 Generating Clients.....................................................................................................................61 Axis Data Binding (ADB).........................................................................................................61 Building Services...........................................................................................................................62 Getting Comfortable with the Available Options......................................................................62 Creating a Service from Scratch...............................................................................................63 Deploying Plain Old Java Objects (POJOs).............................................................................67 Deploying and Running an Axis2 Service Created from WSDL..............................................68 Code Listing 14 - Using the WSDL2Java Utility to Generate the Service..........................68 Code Listing 15 - Compiling the Service.............................................................................70 The Samples...................................................................................................................................73 Clients (in AXIS2_HOME/samples/userguide/src/clients):......................................................73 Services (in AXIS2_HOME/samples/userguide):.....................................................................73 Sample WSDL files (in AXIS2_HOME/samples):...................................................................73 Other samples............................................................................................................................73 In AXIS2_HOME/samples Directory:.................................................................................73 External:...............................................................................................................................74 For Further Study...........................................................................................................................74 Resources..................................................................................................................................74 Apache Axis2 Advanced User's Guide...............................................................................................75 Introduction....................................................................................................................................75 Getting Started...............................................................................................................................75 Creating a New Web Service....................................................................................................75 Starting with WSDL, Creating and Deploying a Service.........................................................75 Step1: Generate Skeleton Code............................................................................................76 Step 2: Implement Business Logic.......................................................................................76 Step 3: Create Archive File..................................................................................................76 Step 4: Deploy Web Service.................................................................................................77 2

Writing a Web Service Client....................................................................................................77 Generate Stubs..........................................................................................................................77 Do a Blocking Invocation.........................................................................................................78 Do a Non-Blocking Invocation.................................................................................................78 Using Your Own Repository.....................................................................................................79 Configuring Axis2..........................................................................................................................80 Axis2 Repository.......................................................................................................................80 Global Configurations...............................................................................................................80 Add New Services.....................................................................................................................80 Engaging Modules....................................................................................................................80 WS-Addressing Support...........................................................................................................81 Advanced Topics............................................................................................................................81 Transports..................................................................................................................................81 Attachments..............................................................................................................................82 Security.....................................................................................................................................82 REST Web Service....................................................................................................................82 Pluggable Data Binding............................................................................................................82 Axis2 Data Binding(ADB)........................................................................................................82 JiBX..........................................................................................................................................82 Other Topics..............................................................................................................................82 Axis2 Configuration Guide................................................................................................................82 Content...........................................................................................................................................83 Global Configuration.....................................................................................................................83 Parameter..................................................................................................................................83 Transport Receiver..................................................................................................................83 Transport Sender.......................................................................................................................84 Phase Order...............................................................................................................................84 Module References....................................................................................................................86 Listeners (Observers)................................................................................................................86 Service Configuration....................................................................................................................87 Module Configuration....................................................................................................................88 Apache Axis2 Web Administrator's Guide.........................................................................................90 Contents.........................................................................................................................................90 Introduction....................................................................................................................................91 Log on to the Administration Site.............................................................................................91 Administration Options..................................................................................................................92 Tools..........................................................................................................................................93 Upload Services....................................................................................................................93 System components...................................................................................................................94 Available Services................................................................................................................94 Available Service Groups.....................................................................................................95 Available Modules................................................................................................................96 Globally Engaged Modules..................................................................................................96 Available Phases...................................................................................................................96 Executions Chains.....................................................................................................................97 Global Chains.......................................................................................................................97 Operation Specific Chains....................................................................................................98 Engaging Modules..................................................................................................................100 Services...................................................................................................................................100 Deactivate Service..............................................................................................................100 3

Activate Service.................................................................................................................101 Edit Service Parameters......................................................................................................102 Contexts..................................................................................................................................103 View Hierarchy...................................................................................................................103 Apache Axis2 Architecture Guide....................................................................................................103 Contents.......................................................................................................................................103 The Big Picture............................................................................................................................104 Requirement of Axis2..................................................................................................................104 Axis2 Architecture.......................................................................................................................105 Core Modules:.........................................................................................................................106 Other Modules:.......................................................................................................................106 Information Model..................................................................................................................107 XML Processing Model..........................................................................................................108 SOAP Processing Model.........................................................................................................109 Axis2 Default Processing Model........................................................................................109 Processing an Incoming SOAP Message............................................................................110 Processing of the Outgoing Message.................................................................................110 Extending the SOAP Processing Model.............................................................................111 Deployment.............................................................................................................................111 The axis2.xml file...............................................................................................................112 Service Archive..................................................................................................................112 Module Archive..................................................................................................................112 Client API................................................................................................................................112 One Way Messaging Support.............................................................................................113 In-Out (Request Response) Messaging Support.................................................................113 Transports................................................................................................................................113 Code Generation......................................................................................................................114 Data Binding...........................................................................................................................115 Integration with the Code Generation Engine....................................................................115 Serialization and De-Serialization of Data bound classes..................................................116 POJO Web Services using Apache Axis2.........................................................................................116 Content.........................................................................................................................................116 Introduction..................................................................................................................................117 The POJO.....................................................................................................................................117 POJO Web Service Using Apache Axis2 and Tomcat.................................................................118 Defining the Service: services.xml..........................................................................................118 Building the POJO Web Service Using Apache Ant....................................................................119 Testing the POJO Web Service Using RPCServiceClient...........................................................120 Limitations and Strengths of POJO........................................................................................122 Spring-based POJO Web Service.................................................................................................122 Quick Introduction..................................................................................................................122 The Service Definition: services.xml......................................................................................122 Initializing the Spring Application Context: SpringInit..........................................................124 Build and Deploy Using Apache Axis2 and Tomcat...............................................................125 Testing Using an RPCServiceClient.......................................................................................125 Summary......................................................................................................................................125 For Further Study.........................................................................................................................125 Axis2 Integration with the Spring Framework.................................................................................126 Content.........................................................................................................................................126 Introduction..................................................................................................................................126 4

Configuring Axis2 to be Spring Aware........................................................................................126 Programming Model...............................................................................................................126 Simple Spring Config Example..............................................................................................127 With a ServletContext.............................................................................................................127 Without a ServletContext........................................................................................................128 Putting It All Together............................................................................................................129 Spring Inside an AAR.............................................................................................................132 The Spring inside an AAR layout ......................................................................................132 The Spring inside an AAR init class .................................................................................133 Known issues running Spring inside the AAR ..................................................................134 Writing Your Own Axis2 Module....................................................................................................134 Content List..................................................................................................................................134 MyService with a Logging Module.............................................................................................135 Step1 : LoggingModule Class.................................................................................................135 Step2 : LogHandler......................................................................................................................136 Step3 : module.xml.................................................................................................................136 Step 4: Modify the "axis2.xml"...............................................................................................137 Step5 : Modify the "services.xml"..........................................................................................139 Step6 : Packaging....................................................................................................................139 Step7 : Deploy the Module in Axis2.......................................................................................139 ADB Data Binding...........................................................................................................................140 Axis2 Databinding Framework....................................................................................................140 Content....................................................................................................................................140 Introduction.............................................................................................................................140 Architectural Overview...........................................................................................................140 Code and Dependencies..........................................................................................................141 Invoking the ADB Code Generator.........................................................................................141 As a Standalone Schema Compiler....................................................................................141 Through the API.................................................................................................................142 Generation Modes...................................................................................................................142 Deep into Generated Code......................................................................................................143 An Example!.......................................................................................................................144 Known Limitations.................................................................................................................145 Want to Learn More?..............................................................................................................145 Advanced Axis2 Databinding Framework Features....................................................................146 Content....................................................................................................................................146 xsi:type Support......................................................................................................................146 Helper mode............................................................................................................................147 Additional ADB Topics...........................................................................................................147 ADB Integration With Axis2.......................................................................................................147 Content....................................................................................................................................147 Introduction.............................................................................................................................148 Selection of Generation Modes for ADB................................................................................148 Things to Remember...............................................................................................................148 ADB Tweaking Guide..................................................................................................................148 Content....................................................................................................................................148 Introduction.............................................................................................................................149 Know the Configuration..............................................................................................................149 The First Tweak - Generate Plain Java Beans.........................................................................149 A More Advanced Tweak - Generate Code for Another Language........................................149 5

JiBx Data Binding............................................................................................................................150 JiBX Integration With Axis2........................................................................................................150 Content....................................................................................................................................150 Introduction.............................................................................................................................150 Wrapped vs. unwrapped..........................................................................................................151 Starting from Java...................................................................................................................151 Starting from WSDL...............................................................................................................152 WSDL2Java usage..................................................................................................................152 Coming Attractions.................................................................................................................152 References...............................................................................................................................153 JiBX general document/literal.....................................................................................................153 JiBX Unwrapped document/literal..............................................................................................157 Advanced..........................................................................................................................................160 Writing Web Services Using Apache Axis2's Primary APIs........................................................160 How to Write a Web Service?.................................................................................................161 Step1: Write the Implementation Class..............................................................................161 Step2: Write the services.xml file.......................................................................................161 Step3: Create the Web Service Archive..............................................................................163 Step4: Deploy the Web Service..........................................................................................163 Writing Web Service Clients Using Axis2's Primary APIs..........................................................164 Request-Response, Blocking Client........................................................................................166 One Way Client.......................................................................................................................166 Request-Response, Non-Blocking that uses one transport connection...................................167 Request-Response, Non-Blocking that uses two transport connections.................................168 Handling Binary Data with Axis2 (MTOM/SwA)...........................................................................169 Content.........................................................................................................................................169 Introduction..................................................................................................................................170 Where Does MTOM Come In?...............................................................................................170 MTOM with Axis2.......................................................................................................................171 Programming Model...............................................................................................................171 Enabling MTOM Optimization on the Client Side.................................................................172 Enabling MTOM Optimization on the Server Side................................................................172 Accessing Received Binary Data (Sample Code)...................................................................173 Service ...............................................................................................................................173 Client .................................................................................................................................173 MTOM Databinding................................................................................................................173 MTOM Databinding Using ADB.......................................................................................174 SOAP with Attachments (SwA) with Axis2................................................................................177 Receiving SwA Type Attachments..........................................................................................177 Sending SwA Type Attachments.............................................................................................178 MTOM Backward Compatibility with SwA...........................................................................179 Advanced Topics..........................................................................................................................180 File Caching for Attachments.................................................................................................180 Transports.........................................................................................................................................181 HTTP Transport...........................................................................................................................181 Content....................................................................................................................................181 CommonsHTTPTransportSender.......................................................................................181 Timeout Configuration.......................................................................................................182 HTTP Version Configuration..............................................................................................182 Proxy Authentication..........................................................................................................183 6

Basic, Digest and NTLM Authentication...........................................................................183 JMS Transport..............................................................................................................................184 Contents..................................................................................................................................184 Overview.................................................................................................................................184 Configuration..........................................................................................................................185 Writing Services to Use the JMS Transport............................................................................186 Echo - Service implementation and services.xml..............................................................186 Echo2 - Service implementation and services.xml............................................................187 Starting up the Axis2 JMS transport.......................................................................................188 TCP Transport..............................................................................................................................188 Content....................................................................................................................................188 Introduction.............................................................................................................................188 How to Start the TCPServer....................................................................................................188 How to Send SOAP Messages Using TCP Transport.............................................................188 Samples...................................................................................................................................189 Transport Components............................................................................................................189 Mail Transport..............................................................................................................................189 Invoking a Service Using a Mail Transport............................................................................189 Content...............................................................................................................................190 Prologue..............................................................................................................................190 Introduction........................................................................................................................190 1. Using the Simple Mail Server Included in Axis2...........................................................190 2. Using a Generic Mail Server..........................................................................................192 Resources............................................................................................................................192 Mail Transport Configuration......................................................................................................192 Content....................................................................................................................................193 Introduction.............................................................................................................................193 Transport Sender.....................................................................................................................193 Transport Receiver..................................................................................................................194 Using Mail Transport in the Server Side.................................................................................195 Using Mail Transport in the Client Side.................................................................................195 Configure James as SMTP and POP Server............................................................................195 Using the Included Mail Server..............................................................................................196 How to Write Your Own Axis2 Transport....................................................................................196 Prologue..................................................................................................................................196 Introduction.............................................................................................................................197 Transport Receiver..................................................................................................................197 Transport Sender.....................................................................................................................199

Introduction Apache Axis2, the third generation Web services engine is more efficient, more modular and more XML-oriented than its predecessor Apache Axis. It is carefully designed to support the easy addition of plug-in modules that extend its functionality for features such as security and increased reliability. Apache Axis2 Version 1.2 comes to you with performance improvements and bug fixes over the 1.1 release. This page will take you through the list of documents that we have in store for you.

7

Apache Axis2 User's Guide You can get started with Axis2 with the assistance of the following documents. They will guide you through the Axis2 download, installation (both as a standalone Web services engine and as part of a J2EE compliant servlet container), and instructions on how to write Web services and Web services client using Apache Axis2. Introduction- Gives you an introduction to what Axis2 is, the life cycle of a Web services message, how Axis2 handles SOAP messages and also includes a basic description on Axis2 distributions, and how Axis2 behaves as part of a Web application or as a standalone client that is not part of a J2EE application. •

Download and Installation- Lists the different distribution packages offered by Axis2 and gives in-depth instructions on the installation of the standalone method and as part of a J2EE servlet container. •

Testing Client Code - The best way to make sure that your system is running Axis2 is to install and test both a service and a client. This document describes this process in easy to understand steps. •

Introduction to Services - The term "Web services" can apply to a number of different ways of sending information back and forth. However, this guide focuses on the sending and receiving of SOAP messages and Message Exchange Patterns (MEPs). •

Creating Clients from WSDL - When it comes to creating a Web service client, you can do it manually as described in the next document. However, in most cases, you will have a Web Service Description Language (WSDL) definition that describes the messages that clients should send and expect to receive. Axis2 provides several ways to use this definition to automatically generate a client. This document explains how to create a client using WSDL definitions. •

Building Services from Scratch - Now that you know how to use Axis2 to generate clients from WSDL as described in the document before, this document digs a little deeper, showing you how to create services, and how to create both services and clients "from scratch", so to speak. •

Samples - The Axis2 Standard Distribution provides a number of samples you can use as a guide for implementing specific features and capabilities. These services are listed in this document along with basic introductions for each one. •



For Further Study - This section lists resource documents for further study. POJO Web Services using Apache Axis2-This guide will show you how to create a Plain Old Java Object (POJO) for deploying using Apache Axis2 on Apache Tomcat. POJOs are fast to build and easy to maintain, which means you'll save a lot of time building and debugging your code •

Axis2 Quick Start Guide-The purpose of this guide is to get you started on creating services and clients using Axis2 as quickly as possible. It demonstrates how to create Web services using a variety of different technologies. •

Also see our FAQ page to answer those common questions in mind.

How To This section deals with more advanced topics including Axis2 support features such as Transports, Attachments, Pluggable Data Binding, Security, and REST Web services in detail. Web Administrator's Guide - Detailed instructions on the administration console of Axis2 Web application, which provides run-time configuration of Axis2. • •

Migrating from Axis 1.x to Axis 2 - Guiding Axis 1.x users in upgrading to Axis2

8

Application Server Specific Configuration Guide - Provides extra configuration information required for application servers to run Axis2 to its fullest potential • •

AXIOM Tutorial-An introduction to Axis2's Object Model



REST Support-Introduction on Representational State Transfer

Axis2 RPC Support - This document talks about the Axis2's Remote Procedure Calls support in a set of easy to understand implementation steps •

MTOM Guide -Sending Binary Data with SOAP - Explains how to send binary data using the SOAP Message Transmission Optimization Mechanism •

Axis2 Configuration Guide - Explains the three configurations in Axis2: global, service, and module •

SOAP Monitor How-to - A guide on the utilities used to monitor the SOAP messages that invoke Web services, along with the results of those messages •

Web Services Policy Support In Axis2 - Introduction to the role of Web services policy in Axis2 • •

Spring Framework - A guide on how to use Axis2 with the Spring Framework

JSON Support - This document explains how to use JSON support implementation in Axis2. Includes details on test cases and samples •

Guide to using EJB Provider in Axis2 - This guide explains how to use an EJB provider in Axis2 using an example. •

Data Bindings: •

ADB How-to - A guide on the Axis2 Databinding Framework (ADB)

Advanced ADB Framework Features - Provides an insight into the newly added advanced features of ADB •

Tweaking the ADB Code Generator - Explains the available mechanisms to extend ADB •

ADB Integration with Axis2 - A guide to writing an extension using the integrator in order to integrate ADB with Axis2 •

JiBX Integration With Axis2 - A guide to using JiBX with Axis2 in order to expose existing Java code as a Web service and to implement a client for an existing Web service •

Transports: •

TCP Transport - A guide to sending and receiving SOAP messages via TCP in Axis2



Mail Transport - Explains how to invoke a service using a Mail transport

Mail Transport Configuration - A guide to configuring Axis2 in order to get mail transport working • •

HTTP Transports - A description on HTTP sender and HTTP receiver in Axis2



JMS Transport - A description on JMS sender and JMS receiver in Axis2

Write Your Own Axis2 Transport - A quick and easy guide to create your own Axis2 Transport protocol •

Axis2 Tools: •

Code Generator Tool Guide for Command Line and Ant Tasks - Lists command line

9

and Ant task references. How to build a file using custom Ant tasks and how to invoke a Code Generator from Ant Code Generator Wizard Guide for Eclipse Plug-in - Explains the usage of the code generator Eclipse plug-in for WSDL2Java and/or Java2WSDL operations •

Service Archive Generator Wizard Guide for Eclipse Plug-in - Describes the functionality of the Eclipse plugin service archive generator tool •

Code Generator Wizard Guide for IntelliJ IDEA Plug-in - A guide on the usage of the IDEA code generation plug-in to create service archives and generate Java class files from WSDL files •

Maven2 AAR Plug-in Guide - A guide to generate an Axis 2 service file (AAR file) using the Maven plug-in. •

Maven2 Java2WSDL Plug-in Guide - A guide to using Java2WSDL Maven 2 Plug-in that takes a Java class as input and generates a WSDL, which describes a Web service for invoking the class methods •

Maven2 WSDL2Code Plug-in Guide - A guide to using this plugin that takes as input a WSDL and generates client and server stubs for calling or implementing a Web service matching the WSDL. •

Apache Axis2 Developers Advanced User's Guide - A quick start user's guide for more experienced users and developers on how to install, create Web services and Web service clients using Axis2. •

Introduction - Outlines the overall direction of the user guide, with a high level introduction on Axis2 •

Download and Installation - Lists the different distribution packages offered by Axis2, and the installations for the standalone and as part of a J2EE servlet container methods. •

Creating a new Web Service with Code Generation - Axis2 provides two ways to create new Web Services: using code generation and XML based primary APIs. This section explains how to start from a WSDL, and create a new Service with code generation •

Writing Web Services Using Axis2's Primary APIs - Explains how to create new Web Services using XML based primary APIs •

Writing a Web Service Client with Code Generation - Axis2 also provides a more complex, yet powerful XML based client API that is intended for advanced users. However, if you are a new user we recommend using the code generation approach presented below •

Writing Web Service Clients Using Axis2's Primary APIs - This section presents complex yet powerful XML based client APIs, which is intended for advanced users to write Web services clients •

Configuring Axis2 - Axis2 configuration is based on a repository and standard archive formats. Here you will find details on how to configure Axis2. You will also find reference documents that lead to greater detail in this area. •



Axis2 Architecture Guide - Introduction to Axis2's modular architecture



Online Java Docs - Java API documentation

Reference Library - This document provides additional information to developers on WS-* specifications, Java language specifications, Subversion (SVN) control etc. •

10

References Gives you a list of published articles, tutorials and Questions-Answers on Apache Axis2. Check them out for that extra knowledge on the next generation Web services engine Apache Axis2. Be Informed and up-to-date!

Apache Axis2 Installation Guide This document provides information on Axis2 distribution packages, system prerequisites and setting up environment variables and tools followed by detailed instructions on installation methods. Send your feedback to: [email protected] mailing list. (Subscription details are available on Axis2 site.) Kindly prefix every email subject with [Axis2].

Contents •

Axis2 Distributions



System Requirements



Install Axis2 as a Standalone Server using Standard Binary Distribution •

Install the Apache Axis2 Binary Distribution



Starting up Axis2 Standalone Server



Building WAR File Using Standard Binary Distribution



Getting Familiar with the Axis2 Convenient Scripts



Install Axis2 in a Servlet Container



Uploading Services



Advanced •

Axis2 Source Distribution •

Setting up the Environment and Tools



Building Axis2 Binaries and the WAR file Using the Source Distribution

Axis2 Distributions Axis2 is distributed in several convenient distribution packages and can be installed either as a standalone server or as part of a J2EE compliant servlet container. Axis2 is distributed under the Apache License, version 2.0. This Installation Guide will mainly focus on running Apache Axis2 using the Standard Binary Distribution. Download distribution packages of the Apache Axis2 1.2 version (latest). Download distribution packages of all versions of Apache Axis2. The Distribution Packages Provided are as follows:

1. Standard Binary Distribution This is the complete version of Axis2 and includes samples and convenient scripts as well. Download Standard Binary Distribution

11

2. WAR (Web Archive) Distribution This is the Web application of Axis2, which can be deployed in most of the servlet containers. Download WAR (Web Archive) Distribution

3. Documents Distribution This contains all the documentation in one package. The package includes the xdocs and the Java API docs of this project. Download Documents Distribution

4. Source Distribution This contains the sources of Axis2 standard distribution, and is mainly for the benefit of the advance users. One can generate a binary distribution using the source by typing $maven distbin. You need to set up the Axis2 environment before running this command. Step by step details on how to create the binary distribution is available in the Advanced section. Download Source Distribution

System Requirements Java Development Kit (JDK)

1.4 or later (For instructions on setting up the JDK in different operating systems, visit http://java.sun.com)

Disk

Approximately 11 MB separately for standard binary distribution

Operating system

Tested on Windows XP, Linux, Mac OS X, Fedora core, Ubuntu, Gentoo

Build Tool-Apache Ant To run samples and to build WAR Version 1.6.5 or higher (download). files from Axis2 binary distribution. Build Tool- Apache Maven 1.x 1.0.2 or higher in Maven 1.x series (download). Please Required only for building Axis2 download Maven 1.x version. Axis2 does not from Source Distribution support Maven 2. Make sure that the above prerequisites are available for the Axis2 installation.

Install Axis2 as a Standalone Server using Standard Binary Distribution This section provides you with the following information 1. Install Axis2 as a standalone server using the Standard Binary Distribution 2. Start up the Axis2 standalone server 3. Building the axis2.war file (using the Standard Binary Distribution) which is required to run Axis2 as part of a J2EE compliant servlet container 4. Running Axis2 convenient scripts

1. Download and Install the Apache Axis2 Binary Distribution Download and install a Java Development Kit (JDK) release (version 1.4 or later). Install the

12

JDK according to the instructions included with the release. Set an environment variable JAVA_HOME to the pathname of the directory into which you installed the JDK release. Download and unpack the Axis2 Standard Binary Distribution into a convenient location so that the distribution resides in its own directory. Set an environment variable AXIS2_HOME to the pathname of the extracted directory of Axis2 (Eg: /opt/axis2-1.2).

2. Starting up Axis2 Standalone Server Standalone Axis2 server can be started by executing the following commands: $AXIS2_HOME\bin\axis2server.bat (Windows) $AXIS2_HOME/bin/axis2server.sh (Unix) After startup, the default web services included with Axis2 will be available by visiting http://localhost:8080/axis2/services/

3. Building the Axis2 Web Application (axis2.war) Using Standard Binary Distribution Download and install Apache Ant (version 1.6.5 or later). Install Apache Ant according to the instructions included with the Ant release. Locate the Ant build file (build.xml) inside the webapp directory, which resides in your Axis2 home directory (i.e:- $AXIS_HOME/webapp)". Run the Ant build by executing "ant create.war" inside the $AXIS2_HOME/webapps folder. You can find the generated axis2.war inside the $AXIS2_HOME/dist directory. All the services and modules that are present in the AXIS2_HOME/repository will be packed into the created axis2.war together with the Axis2 configuration found at $AXIS2_HOME/conf/axis2.xml. Read Installing Axis2 in a Servlet Container to find out how to deploy the Axis2 Web application in a servlet container.

4. Getting Familiar with the Axis2 Convenient Scripts It is advised to add the $AXIS2_HOME/bin to the PATH, so that you'll be able to run the following scripts from any where. Script Name

Description You can use this script to run web service clients written using Axis2. This script calls the "java" command after adding the classpath for Axis2 dependent libraries (*.jar files present in your AXIS2_HOME/lib), setting the Axis2 axis2.{bat| repository location (AXIS2_HOME/repository) and setting the Axis2 sh} configuration file location(AXIS2_HOME/conf/axis2.xml) for you. With this you can be relieved from setting all the above Axis2 specific parameters. Usage : axis2.{sh.bat} [-options] class [args...] This script will start a standalone Axis2 server using the AXIS2_HOME/repository as the Axis2 repository and the AXIS2_HOME/conf/axis2.xml as the Axis2 configuration file. This will start all the transport listeners listed in the AXIS2_HOME/conf/axis2.xml. axis2server.{ For example, if you want to deploy a service using a standalone Axis2 sh|bat} server,then copy your service archive to the AXIS2_HOME/repository/services directory. Next, go to the "Transport Ins" section of the AXIS2_HOME/conf/axis2.xml and configure the transport receivers (simpleHttpServer in port 8080 is listed by default). Then invoke this script. wsdl2java.{b This script generates Java code according to a given WSDL file to handle Web at|sh} service invocations (Client side Stubs). This script also has the ability to generate service skeletons according to the given WSDL.

13

Usage: wsdl2java.{sh|bat} [OPTION]... -uri e.g., wsdl2java.sh -uri ../wsdl/Axis2Sample.wsdl A more detailed reference about this script can be found here This script generates the appropriate WSDL file for a given Java class. java2wsdl.{b Usage: Java2WSDL.{sh|bat} [OPTION]... -cn at|sh} e.g., Java2WSDL.sh -cn ../samples/test/searchTool.Search A more detailed reference about this script can be found here

Install Axis2 in a Servlet Container Which ever the distribution, installing Axis2 in a J2EE compliant servlet container is as follows: 1. Build the Axis2 WAR file using the Axis2 Standard Binary Distribution. (Alternatively you can download the axis2.war file or you can build axis2.war using the Source Distribution. 2. Drop the WAR file in the webapps folder of the servlet container. Most servlet containers will automatically install the WAR file. (Some servlet containers may require a restart in order to capture the new web application. Refer to your servlet container documentation for more information.) 3. Once the WAR is successfully installed, test it by pointing the web browser to the http:///axis2. It should produce the following page which is the Axis2 Web Application Home Page.

4. Use the link "Validate" to ensure that everything is fine and smooth. If the validation fails then the WAR has failed to install properly or some essential jars are missing. In such a situation, refer to the documentation of the particular servlet container to find the problem. The following page is a successful validation. Note that the statement core Axis2 libraries are present.

14

15

16

17

18

Note: For any Application server specific installation information please refer to the Application Server Specific Configuration Guide.

Uploading Services The Axis2 Web application also provides an interface to upload services. Once a service is created according to the service specification as described in the Advanced User's Guide, that .jar file can be uploaded using the upload page.

19

The uploaded .jar files will be stored in the default service directory. For Axis2, this will be the <webapps>/axis2/WEB-INF/services directory. Once a service is uploaded, it will be installed instantly. Since Axis2 supports hot deployment, you can drop the service jar directly through the file system to the above mentioned services directory. It will also cause the service to be automatically installed without the container being restarted. Use the 'Services' link on the Web Application home page to check the successful installation of a service. The services and the operations of successfully installed services will be displayed on the available services page.

20

If the service has deployment time errors it will list those services as faulty services. If you click on the link, you will see the deployment fault error messages.

Deployment time error message

21

22

Axis2 Administration is all about configuring Axis2 at the run time and the configuration will be transient. More descriptions are available in the Axis2 Web Administration Guide

Advanced Axis2 Source Distribution By using the Source Distribution, both binary files (which can be downloaded as the Standard Binary Distribution) and the axis2.war file (which can be downloaded as the WAR distribution) can be built using Maven commands. Required jar files do not come with the distribution and they will also have to be built by running the maven command. Before we go any further, it is necessary to install Maven

Setting Up the Environment and Tools Maven The Axis2 build is based on Maven . Hence the only prerequisite to build Axis2 from the source distribution is to have Maven installed. Extensive instruction guides are available at the Maven site. This guide however contains the easiest path for quick environment setting. Advanced users who wish to know more about Maven can visit this site. •

MS Windows

1. Download and run the Windows installer package for Maven. 2. Set the 'Environment Variables' ( create system variable MAVEN_HOME and edit path. eg: "C:\Program Files\Apache Software Foundation\maven-1.0.2"; path %MAVEN_HOME%\bin) 3. Make sure that the system variable JAVA_HOME is set to the location of your JDK, eg. C:\Program Files\Java\jdk1.5.0_02 4. Run maven --version to verify that it is correctly installed.

23



Unix based OS (Linux etc)

The tar ball or the zip archive is the best option. Once the archive is downloaded expand it to a directory of choice and set the environment variable MAVEN_HOME and add MAVEN_HOME/bin to the path as well. More instructions for installing Maven in Unix based operating systems. Once Maven is properly installed, you can start building Axis2. Maven commands that are frequently used in Axis2 are listed on the FAQs page.

Building Binaries and the WAR File Using the Source Distribution The Source Distribution is available as a zipped archive. All the necessary build scripts are included with the source distribution. Once the source archive is expanded into a directory of choice, moving to the particular directory and running maven command will build the Axis2 jar file.

Once the command completes, the binaries (jar files in this case) can be found at a newly created "target" directory. Note: For the first Maven build (if the maven repository is not built first) it will take a while since the required jars need to be downloaded. However, this is a once only process and will not affect any successive builds. The default maven build will however build only the Axis2 jar file. To obtain a WAR (Web Archive), maven war command should be issued. This will create a complete WAR with the name axis2.war inside the target directory. Once this build step is complete, the binaries are ready to be deployed.

Apache Axis2 Modules Axis2 architecture is flexible enough to extend its functionalities using modules. This page is maintained to keep track of the relevant modules that are developed on top of Axis2.

Name Addressing

Compatible Version Axis2 Downloads version

Description This is an implementation of WSAddressing submission version (200408) and WS-Addressing 2005-08

24

1.2

1.2

mar MD5 PGP

SOAP Monitor

Sandesha2

Rampart

versions. SOAP Monitor utility provides a way for Web services developers to monitor the SOAP messages being sent/received without requiring any special configuration or restarting of the server An implementation of WS-RM specification February 2005 The WS-Security and WSSecureConversation implementation for axis2. Now with a new configuration model based on WS-SecurityPolicy

1.2

1.2

zip MD5 PGP

1.2

1.2

zip MD5 PGP

1.2

1.2

zip MD5 PGP

Previous module releases are available here

Application Server Specific Configuration Guide This document provides configuration information required for your Application Server to run Apache Axis2 to its fullest potential. Send your feedback or questions to: [email protected]. ( Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

WebLogic/ WebSphere 1. Use exploded configuration to deploy Axis2 WAR We recommend using the exploded configuration to deploy Axis2 WAR in WebLogic and WebSphere application servers to support the hotupdate/ hotdeployment features in Axis2. However, if you do want to deploy custom WARs, say in a clustering environment, you need to add two additional files into the WEB-INF named "services.list" and "modules.list" under the modules and services directory respectively. WEB-INF/services/services.list : should list all the services (aar files) that you want to expose. •

WEB-INF/modules/modules.list : should list all the modules (mar files) that you want to use. •

NOTE: In both cases, please list one entry per line. WebLogic ships with JARs that conflict with JARs present in Axis2. Therefore use <preferweb-inf-classes> to ensure that JARs packaged in Axis2 WAR are picked up from WEB-INF/lib. You can do this by setting the <prefer-web-inf-classes> element in WEB-INF/weblogic.xml to true. An example of weblogic.xml is shown below: <weblogic-web-app> <prefer-web-inf-classes>true If set to true, the <prefer-web-inf-classes> element will force WebLogic's classloader to load

25

classes located in the WEB-INF directory of a Web application in preference to application or system classes. This is a recommended approach since it only impacts a single Web module. Please refer to the following documents in WebLogic/ WebSphere for more information: WebLogic ServerApplication Classloading- For more information on how WebLogic's class loader works • •

Redeploying a Web Application in Exploded Directory Format



Deploying the Web application in exploded form

2. Lack of namespacing on serialised items BEA WebLogic Server 9.0 comes with its own StAX implementation. This results in lack of namespacing on serialised items. In turn, WeLogic server (WLS) breaks with AXIOM on the WLS classpath. Hence a filtering classloader is required: Adding the following to weblogic-application.xml should resolve the issue: <prefer-application-packages> <package-name>com.ctc.wstx.* <package-name>javax.xml.* <package-name>org.apache.*

Note that the classes - Xerces, StAX API, Woodstox need to be on the application classpath

Axis2 Quick Start Guide The purpose of this guide is to get you started on creating services and clients using Axis2 as quickly as possible. We'll take a simple StockQuote Service and show you some of the different ways in which you can create and deploy it, as well as take a quick look at one or two utilities that come with Axis2. We'll then look at creating clients to access those services.

Content •

Introduction



Getting Ready



Axis2 services



Creating services





Deploying POJOs



Building the service using AXIOM



Generating the service using ADB



Generating the service using XMLBeans



Generating the service using JiBX

Generating Clients •

Creating a client using AXIOM



Generating a client using ADB



Generating a client using XML Beans

26



Generating a client using JiBX



Summary



For Further Study

A Quick Setup Note: The code for the document can be found in the extracted Standard Binary Distribution, more specifically at Axis2_HOME/samples/ inside the directories- quickstart, quickstartadb, quickstartaxiom, quickstartjibx and quickstartxmlbeans. (Consider getting it now as it will help you to follow along.) It includes Ant buildfiles (build.xml) that we'll refer to throughout the examples to make compilation easier.

Introduction Let's start with the service itself. We'll make it simple so you can see what is going on when we build and deploy the services. A StockQuoteService example seems to be mandatory in instances like this one, so let's use the following (see Code Listing 1). Code Listing 1: The StockQuoteService class

27

28

29

30

31

32

package samples.quickstart.service.pojo; import java.util.HashMap; public class StockQuoteService { private HashMap map = new HashMap(); public double getPrice(String symbol) { Double price = (Double) map.get(symbol); if(price != null){ return price.doubleValue(); } return 42.00; }

}

public void update(String symbol, double price) { map.put(symbol, new Double(price)); }

It will be a simple service with two possible calls. One of which is an in/out message, and the other is an in-only service. Ultimately, we'll package the service and deploy it in four different ways. First, let's look at how this simple Java class corresponds to a service.

Getting Ready Before we build anything using Axis2, we have to take care of a little housekeeping. First off, you'll need to get your environment ready for working with Axis2. Fortunately, it involves just a few simple steps: 1. Download and install Java. (Minimum version is JDK1.4) 2. Download Axis2 and extract it to a target directory. 3. Copy the axis2.war file to the webapps directory of your servlet engine. 4. Set the AXIS2_HOME environment variable to point to the target directory in step. Note that all of the scripts and build files Axis2 generates depend on this value, so don't skip this step! In most cases, we're also going to need a WSDL file for our service. Axis2's Java2WSDL can be used to bootstrap a WSDL. To generate a WSDL file from a Java class, perform the following steps: 1. Create and compile the Java class. 2. Generate the WSDL using the command: %AXIS2_HOME%/bin/java2wsdl -cp . -cn samples.quickstart.service.pojo.StockQuoteService -of StockQuoteService.wsdl Once you've generated the WSDL file, you can make the changes you need. For example, you might add custom faults or change the name of the generated elements. For example, this StockQuoteService.wsdl is in %AXIS2_HOME%/samples/quickstartadb/resources/META-INF folder, which we'll be using throughout the rest of this guide, replaces the generic parameters created by the generation process.

33

Axis2 Services Before we build anything, it's helpful to understand what the finished product looks like. The server side of Axis2 can be deployed on any Servlet engine, and has the following structure. Shown in Code Listing 2. Code Listing 2: The Directory Structure of axis2.war axis2-web META-INF WEB-INF classes conf axis2.xml lib activation.jar ... xmlSchema.jar modules modules.list addressing.mar ... soapmonitor.mar services services.list aservice.aar ... version.aar web.xml

Starting at the top, axis2-web is a collection of JSPs that make up the Axis2 administration application, through which you can perform any action such as adding services and engaging and dis-engaging modules. The WEB-INF directory contains the actual java classes and other support files to run any services deployed to the services directory. The main file in all this is axis2.xml, which controls how the application deals with the received messages, determining whether Axis2 needs to apply any of the modules defined in the modules directory. Services can be deployed as *.aar files, as you can see here, but their contents must be arranged in a specific way. For example, the structure of this service will be as follows: - StockQuoteService - META-INF - services.xml - lib - samples - quickstart - service - pojo - StockQuoteService.class Here, the name of the service is StockQuoteService, which is specified in the services.xml file and corresponds to the top-level folder of this service. Compiled Java classes are placed underneath this in their proper place based on the package name. The lib directory holds any service-specific JAR files needed for the service to run (none in this case) besides those already stored with the Axis2 WAR file and the servlet container's common JAR directories.

34

Finally, the META-INF directory contains any additional information about the service that Axis2 needs to execute it properly. The services.xml file defines the service itself and links the Java class to it (See Code Listing 3). Code Listing 3: The Service Definition File <service name="StockQuoteService" scope="application"> <description> Stock Quote Sample Service <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass"> samples.quickstart.service.pojo.StockQuoteService Here the service is defined, along with the relevant messageReceiver types for the different message exchange patterns. The META-INF directory is also the location for any custom WSDL files you intend to include for this application. You can deploy a service by simply taking this hierarchy of files and copying it to the webapps directory of your servlet engine. This is known as the "exploded" format. You can also compress your documents into an *.aar file, similar to a *.jar file, and place the *.aar file directly in the servlet engine's webapps directory. Now that you understand what we're trying to accomplish, we're almost ready to start building. First, download and unzip the appropriate version of Axis2 Standard Binary Distribution. Make sure that you set the value of the AXIS2_HOME variable to match the location into which you extracted the contents of this release. Let's look at some different ways to create clients and services.

Creating Services In this section, we'll look at five ways to create a service based on the StockQuoteService class: deploying Plain Old Java Objects (POJO), building the service using AXIOM's OMElement, generating the service using Axis2 Databinding Framework (ADB), generating the service using XMLBeans, and generating the service using JiBX.

Deploying POJOs To deploy the service using POJOs (Plain Old Java Objects), execute the following steps. Note the directory structure contained at /samples/quickstart services.xml file is from the first section of this guide):

35

(the

- quickstart - README.txt - build.xml - resources - META-INF - services.xml - src - samples - quickstart - service - pojo - StockQuoteService.java Note that you can generate a WSDL from the quickstart directory by typing: ● ant generate.wsdl However, creating StockQuoteService.wsdl is optional. It can be the version generated directly from the Java class, or a customized version of that file, and that services.xml is the same file referenced earlier in this document. Now build the project by typing ant generate.service in the quickstart directory, which creates the following directory structure: - quickstart/build/classes - META-INF - services.xml - samples - quickstart - service - pojo - StockQuoteService.class If you want to deploy the service in an exploded directory format, rename the classes directory to StockQuoteService, and copy it to the webapps/axis2/WEB-INF/services directory in your servlet engine. Otherwise, copy the build/StockQuoteService.aar file to the webapps/axis2/WEB-INF/services directory in your servlet engine. Then check to make sure that the service has been properly deployed by viewing the list of services at: ●

http://localhost:8080/axis2/services/listServices

You can also checkout the WSDL at: ●

http://localhost:8080/axis2/services/StockQuoteService?wsdl

And the schema at: ●

http://localhost:8080/axis2/services/StockQuoteService?xsd

Once the URLs are working, quickly test the service. Try pointing your browser to the following URL: ●

http://localhost:8080/axis2/services/StockQuoteService/getPrice?symbol=IBM

You will get the following response: <ns:getPriceResponse xmlns:ns="http://pojo.service.quickstart.samples/xsd"><ns:return>42 If you invoke the update method as, ●

http://localhost:8080/axis2/services/StockQuoteService/update?symbol=IBM&p

36

rice=100 and then execute the first getPrice URL, you will see that the price has got updated.

Building the Service using AXIOM To build a service "from scratch" using AXIOM, execute the following steps. Note the directory structure contained at /samples/quickstartaxiom: - quickstartaxiom - README.txt - build.xml - resources - META-INF - services.xml - StockQuoteService.wsdl - src - samples - quickstart - service - axiom - StockQuoteService.java - clients - AXIOMClient.java Since AXIOM is a little different, you're going to need a different services.xml file from the one used for POJO. Define it, as shown in Code Listing 4. Code Listing 4: The Service Definition File. <service name="StockQuoteService" scope="application"> <description> Stock Quote Service <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> <parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService Note that it's almost the same, except that the operations are explicitly defined in the service.xml file, and the MessageReceivers are now RawXML. Now, the above referenced StockQuoteService.java class, a plain Java class that uses classes from the Axis2 libraries, is defined as shown in Code Listing 5. Code Listing 5: The StockQuoteService Class using AXIOM

37

38

39

package samples.quickstart.service.axiom; import import import import import

javax.xml.stream.XMLStreamException; org.apache.axiom.om.OMAbstractFactory; org.apache.axiom.om.OMElement; org.apache.axiom.om.OMFactory; org.apache.axiom.om.OMNamespace;

import java.util.HashMap; public class StockQuoteService { private HashMap map = new HashMap(); public OMElement getPrice(OMElement element) throws XMLStreamException { element.build(); element.detach(); OMElement symbolElement = element.getFirstElement(); String symbol = symbolElement.getText(); String returnText = "42"; Double price = (Double) map.get(symbol); if(price != null){ returnText = "" + price.doubleValue(); } OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.sampl es/xsd", "tns"); OMElement method = fac.createOMElement("getPriceResponse", omNs); OMElement value = fac.createOMElement("price", omNs); value.addChild(fac.createOMText(value, returnText)); method.addChild(value); return method; } public void update(OMElement element) throws XMLStreamException { element.build(); element.detach(); OMElement symbolElement = element.getFirstElement(); String symbol = symbolElement.getText(); OMElement priceElement = (OMElement)symbolElement.getNextOMSibling(); String price = priceElement.getText(); map.put(symbol, new Double(price)); }

}

Axis2 uses AXIOM, or the AXIs Object Model, a DOM (Document Object Model)-like structure that is based on the StAX API (Streaming API for XML). Methods that act as services must take as their argument an OMElement, which represents an XML element that happens, in this case, to be the payload of the incoming SOAP message. Here, you're extracting the contents of the first child of the payload element, adding text to it, and using it as content for the return OMElement. Unless this is an "in only" service, these methods must return an OMElement, because that becomes the payload of the return SOAP message.

40

Now build the project by typing Axis2_HOME/samples/quickstartaxiom directory.

ant

generate.service

in

the

Place the StockQuoteService.aar file in the webapps/axis2/WEB-INF/services directory of the servlet engine, and check to make sure that the service has been properly deployed by viewing the list of services at, ●

http://localhost:8080/axis2/services/listServices

You can also check the custom WSDL at, ●

http://localhost:8080/axis2/services/StockQuoteService?wsdl

and the schema at, ●

http://localhost:8080/axis2/services/StockQuoteService?xsd

Generating the Service using ADB To generate and deploy the service using the Axis2 Databinding Framework (ADB), execute the following steps. Generate the skeleton using the WSDL2Java utility by typing the following in the Axis2_HOME/samples/quickstartadb directory: %AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.adb -d adb -s -ss -sd -ssi -o build/service Else, simply type ant generate.service in the Axis2_HOME/samples/quickstartadb directory. The option -d adb specifies Axis Data Binding (ADB). The -s switch specifies synchronous or blocking calls only. The -ss switch creates the server side code (skeleton and related files). The -sd switch creates a service descriptor (services.xml file). The -ssi switch creates an interface for the service skeleton. The service files should now be located at build/service. If you generated the code by using WSDL2Java directly, next you have to modify the generated skeleton to implement the service (if you used "ant generate.service", a completed skeleton will be copied over the generated one automatically). Open the build/service/src/samples/quickstart/adb/service/StockQuoteServiceSkeleton.java file and modify it to add the functionality of your service to the generated methods; shown in Code Listing 6. Code Listing 6: Defining the Service Skeleton File

41

package samples.quickstart.service.adb; import samples.quickstart.service.adb.xsd.GetPriceResponse; import samples.quickstart.service.adb.xsd.Update; import samples.quickstart.service.adb.xsd.GetPrice; import java.util.HashMap; public class StockQuoteServiceSkeleton { private static HashMap map; static{ map = new HashMap(); } public void update(Update param0) { map.put(param0.getSymbol(), new Double(param0.getPrice())); } public GetPriceResponse getPrice(GetPrice param1) { Double price = (Double) map.get(param1.getSymbol()); double ret = 42; if(price != null){ ret = price.doubleValue(); } GetPriceResponse res = new GetPriceResponse(); res.set_return(ret); return res; } } Now you can build the project by typing the following command in the build/service directory: ●

ant jar.server

If all goes well, you should see the BUILD SUCCESSFUL message in your window, and the StockQuoteService.aar file in the build/service/build/lib directory. Copy this file to the webapps/axis2/WEB-INF/services directory of the servlet engine. You can check to make sure that the service has been properly deployed by viewing the list of services at, ●

http://localhost:8080/axis2/services/listServices

You can also check the custom WSDL at, ●

http://localhost:8080/axis2/services/StockQuoteService?wsdl

and the schema at, ●

http://localhost:8080/axis2/services/StockQuoteService?xsd

Generating the Service using XMLBeans To generate a service using XMLBeans, execute the following steps. Generate the skeleton using the WSDL2Java utility by typing the following in the Axis2_HOME/samples/quickstartxmlbeans directory. %AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -ss -sd -ssi -o build/service

42

Else simply type ant generate.service in the Axis2_HOME/samples/quickstartxmlbeans directory. The option -d xmlbeans synchronous or blocking calls related files). The -sd switch creates an interface for the build/service.

specifies XML Beans data binding. The -s switch specifies only. The -ss switch creates the server side code (skeleton and creates a service descriptor (services.xml file). The -ssi switch service skeleton. The service files should now be located at

If you generated the code by using WSDL2Java directly, next you have to modify the generated skeleton to implement the service (if you used "ant generate.service", a completed skeleton will be copied over the generated one automatically). Next open the build/service/src/samples/quickstart/service/xmlbeans/StockQuoteServiceSkeleton.java file and modify it to add the functionality of your service to the generated methods (see Code Listing 7). Code Listing 7: Defining the Service Skeleton package samples.quickstart.service.xmlbeans; import samples.quickstart.service.xmlbeans.xsd.GetPriceDocument; import samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument; import samples.quickstart.service.xmlbeans.xsd.UpdateDocument; import java.util.HashMap; public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface { private static HashMap map; static{ map = new HashMap(); } public void update(UpdateDocument param0) { map.put(param0.getUpdate().getSymbol(), new Double(param0.getUpdate().getPrice())); } public GetPriceResponseDocument getPrice(GetPriceDocument param1) { Double price = (Double) map.get(param1.getGetPrice().getSymbol()); double ret = 42; if(price != null){ ret = price.doubleValue(); } System.err.println(); GetPriceResponseDocument resDoc = GetPriceResponseDocument.Factory.newInstance(); GetPriceResponseDocument.GetPriceResponse res = resDoc.addNewGetPriceResponse(); res.setReturn(ret); return resDoc; } }

Build the project by typing the following command in the build/service directory, which contains the build.xml file: ●

ant jar.server

43

If all goes well, you should see the BUILD SUCCESSFUL message in your window, and the StockQuoteService.aar file in the newly created build/service/build/lib directory. Copy this file to the webapps/axis2/WEB-INF/services directory of the servlet engine. You can check to make sure that the service has been properly deployed by viewing the list of services at, ●

http://localhost:8080/axis2/services/listServices

You can also check the custom WSDL at, ●

http://localhost:8080/axis2/services/StockQuoteService?wsdl

and the schema at, ●

http://localhost:8080/axis2/services/StockQuoteService?xsd

Generating the Service using JiBX To generate and deploy the service using JiBX data binding, execute the following steps. Generate the skeleton using the WSDL2Java utility by typing the following at a console in the Axis2_HOME/samples/quickstartjibx directory: %AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.jibx -d jibx -s -ss -sd -ssi -uw -o build/service Else, simply directory.

type

"ant

generate.service"

in

the

Axis2_HOME/samples/quickstartjibx

The option -d jibx specifies JiBX data binding. The -s switch specifies synchronous or blocking calls only. The -ss switch creates the server side code (skeleton and related files). The -sd switch creates a service descriptor (services.xml file). The -ssi switch creates an interface for the service skeleton. The -uw switch unwraps the parameters passed to and from the service operations in order to create a more natural programming interface. After running WSDL2Java, the service files should be located at build/service. If you generated the code by using WSDL2Java directly, you need to modify the generated skeleton to implement the service (if you used "ant generate.service" a completed skeleton will be copied over the generated one automatically). Open the build/service/src/samples/quickstart/service/jibx/StockQuoteServiceSkeleton.java file and modify it to add the functionality of your service to the generated methods, as shown in Code Listing 8. Code Listing 8: Defining the Service Skeleton File

44

package samples.quickstart.service.jibx; import java.util.HashMap; public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface { private HashMap map = new HashMap(); public void update(String symbol, Double price) { map.put(symbol, price); } public Double getPrice(String symbol) { Double ret = (Double) map.get(symbol); if (ret == null) { ret = new Double(42.0); } return ret; } } Now you can build the project by typing the following command in the build/service directory: ●

ant jar.server

If all goes well, you should see the BUILD SUCCESSFUL message in your window, and the StockQuoteService.aar file in the build/service/build/lib directory. Copy this file to the webapps/axis2/WEB-INF/services directory of the servlet engine. You can check to make sure that the service has been properly deployed by viewing the list of services at, ●

http://localhost:8080/axis2/services/listServices

You can also check the custom WSDL at, ●

http://localhost:8080/axis2/services/StockQuoteService?wsdl

and the schema at, ●

http://localhost:8080/axis2/services/StockQuoteService?xsd

For more information on using JiBX with Axis2, see the JiBX code generation integration details. You can also check the JiBX Axis2 Wiki page for updated information about using JiBX with Axis2.

Creating Clients In this section, we'll look at four ways to create clients based on the StockQuoteService class: building an AXIOM based client, generating a client using Axis2 Databinding Framework (ADB), generating a client using XMLBeans, and generating a client using JiBX.

Creating a Client with AXIOM To build a client using AXIOM, execute the following steps. Also, note the directory structure shown in the Creating a service with AXIOM section, duplicated below for completeness.

45

- quickstartaxiom - README.txt - build.xml - resources - META-INF - services.xml - StockQuoteService.wsdl - src - samples - quickstart - service - axiom - StockQuoteService.java - clients - AXIOMClient.java The above referenced AXIOMClient.java class is defined as follows, shown in Code Listing 9. Code Listing 9: The AXIOMClient class using AXIOM package samples.quickstart.clients; import import import import import import import import

org.apache.axiom.om.OMAbstractFactory; org.apache.axiom.om.OMElement; org.apache.axiom.om.OMFactory; org.apache.axiom.om.OMNamespace; org.apache.axis2.Constants; org.apache.axis2.addressing.EndpointReference; org.apache.axis2.client.Options; org.apache.axis2.client.ServiceClient;

public class AXIOMClient { private static EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/StockQuoteServic e"); public static OMElement getPricePayload(String symbol) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");

}

OMElement method = fac.createOMElement("getPrice", omNs); OMElement value = fac.createOMElement("symbol", omNs); value.addChild(fac.createOMText(value, symbol)); method.addChild(value); return method;

46

public static OMElement updatePayload(String symbol, double price) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns"); OMElement method = fac.createOMElement("update", omNs); OMElement value1 = fac.createOMElement("symbol", omNs); value1.addChild(fac.createOMText(value1, symbol)); method.addChild(value1); OMElement value2 = fac.createOMElement("price", omNs); value2.addChild(fac.createOMText(value2, Double.toString(price))); method.addChild(value2); return method; } public static void main(String[] args) { try { OMElement getPricePayload = getPricePayload("WSO"); OMElement updatePayload = updatePayload("WSO", 123.42); Options options = new Options(); options.setTo(targetEPR); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); ServiceClient sender = new ServiceClient(); sender.setOptions(options); sender.fireAndForget(updatePayload); System.err.println("done"); OMElement result = sender.sendReceive(getPricePayload); String response = result.getFirstElement().getText(); System.err.println("Current price of WSO: " + response);

}

} catch (Exception e) { e.printStackTrace(); }

} Axis2 uses AXIOM, or the AXIs Object Model, a DOM (Document Object Model)-like structure that is based on the StAX API (Streaming API for XML). Here you setup the payload for the update and getPrice methods of the service. The payloads are created similar to how you created the getPriceResponse payload for the AXIOM service. Then you setup the Options class, and create a ServiceClient that you'll use to communicate with the service. First you call the update method, which is a fireAndForget method that returns nothing. Lastly, you call the getPrice method, and retrieve the current price from the service and display it.

Now you can build and run the AXIOM client by typing ant run.client in the Axis2_HOME/samples/quickstartaxiom directory. You should get the following as output: done Current price of WSO: 123.42

47

Generating a Client using ADB To build a client using Axis Data Binding (ADB), execute the following steps. Generate the client databings by Axis2_HOME/samples/quickstartadb directory:

typing

the

following

in

the

%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d adb -s -o build/client Else, simply type ant generate.client in the Axis2_HOME/samples/quickstartadb directory. Next take a look at quickstartadb/src/samples/quickstart/clients/ADBClient.java, and see how it's defined in Code Listing 10. Code Listing 10: The ADBClient Class package samples.quickstart.clients; import samples.quickstart.service.adb.StockQuoteServiceStub; public class ADBClient{ public static void main(java.lang.String args[]){ try{ StockQuoteServiceStub stub = new StockQuoteServiceStub ("http://localhost:8080/axis2/services/StockQuoteService "); getPrice(stub); update(stub);

}

} catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); }

/* fire and forget */ public static void update(StockQuoteServiceStub stub){ try{ StockQuoteServiceStub.Update req = new StockQuoteServiceStub.Update(); req.setSymbol ("ABC"); req.setPrice (42.35);

}

stub.update(req); System.err.println("done"); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); }

48

/* two way call/receive */ public static void getPrice(StockQuoteServiceStub stub){ try{ StockQuoteServiceStub.GetPrice req = new StockQuoteServiceStub.GetPrice(); req.setSymbol("ABC"); StockQuoteServiceStub.GetPriceResponse res = stub.getPrice(req);

}

System.err.println(res.get_return()); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); }

} This class creates a client stub using the Axis Data Bindings you created. Then it calls the getPrice and update operations on the Web service. The getPrice method operation creates the GetPrice payload and sets the symbol to ABC. It then sends the request and displays the current price. The update method creates an Update payload, setting the symbol to ABC and the price to 42.35. Now build and run the client Axis2_HOME/samples/quickstartadb directory.

by

typing

ant

run.client

in

the

You should get the following as output: 42 done

Generating a Client using XMLBeans To build a client using the XML Beans data bindings, execute the following steps. Generate the databings by typing the following in the xmlbeansClient directory. %AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -o build/client Else, simply type ant generate.client in the Axis2_HOME/samples/quickstartxmlbeans directory. Note that this creates a client stub code and no server side code. Next take a look quickstartxmlbeans/src/samples/quickstart/clients/XMLBEANSClient.java, and defined in Code Listing 11. Code Listing 11: The XMLBEANSClient class

49

see

how

at it's

package samples.quickstart.clients; import import import import

samples.quickstart.service.xmlbeans.StockQuoteServiceStub; samples.quickstart.service.xmlbeans.xsd.GetPriceDocument; samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument; samples.quickstart.service.xmlbeans.xsd.UpdateDocument;

public class XMLBEANSClient{

");

public static void main(java.lang.String args[]){ try{ StockQuoteServiceStub stub = new StockQuoteServiceStub ("http://localhost:8080/axis2/services/StockQuoteService getPrice(stub); update(stub); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } }

/* fire and forget */ public static void update(StockQuoteServiceStub stub){ try{ UpdateDocument reqDoc = UpdateDocument.Factory.newInstance(); UpdateDocument.Update req = reqDoc.addNewUpdate(); req.setSymbol ("ABC"); req.setPrice (42.32);

}

stub.update(reqDoc); System.err.println("done"); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); }

/* two way call/receive */ public static void getPrice(StockQuoteServiceStub stub){ try{ GetPriceDocument reqDoc = GetPriceDocument.Factory.newInstance(); GetPriceDocument.GetPrice req = reqDoc.addNewGetPrice(); req.setSymbol("ABC"); GetPriceResponseDocument res = stub.getPrice(reqDoc);

}

System.err.println(res.getGetPriceResponse().getReturn()); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); }

}

50

This class creates a client stub using the XML Beans data bindings you created. Then it calls the getPrice and the update operations on the Web service. The getPrice method operation creates the GetPriceDocument, its inner GetPrice classes and sets the symbol to ABC. It then sends the request and retrieves a GetPriceResponseDocument and displays the current price. The update method creates an UpdateDocument, updates and sets the symbol to ABC and price to 42.32, displaying 'done' when complete. Now build and run the the project by Axis2_HOME/samples/quickstartxmlbeans directory.

typing

ant

run.client

in

the

console

in

the

You should get the following as output: 42 done

Generating a Client using JiBX To build a client using JiBX, execute the following steps. Generate the client stub by typing Axis2_HOME/samples/quickstartjibx directory.

the

following

at

a

%AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d jibx -s -uw -o build/client Else, simply type "ant generate.client". Next take a look at quickstartjibx/src/samples/quickstart/clients/JiBXClient.java, shown below in Code Listing 12. Code Listing 12: The JiBXClient class package samples.quickstart.clients; import samples.quickstart.service.jibx.StockQuoteServiceStub; public class JiBXClient{ public static void main(java.lang.String args[]){ try{ StockQuoteServiceStub stub = new StockQuoteServiceStub ("http://localhost:8080/axis2/services/StockQuoteService "); getPrice(stub); update(stub); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } }

51

/* fire and forget */ public static void update(StockQuoteServiceStub stub){ try{ stub.update("ABC", new Double(42.35)); System.err.println("done"); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } } /* two way call/receive */ public static void getPrice(StockQuoteServiceStub stub){ try{ System.err.println(stub.getPrice("ABC")); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } } } This class uses the created JiBX client stub to access the getPrice and the update operations on the Web service. The getPrice method sends a request for the stock "ABC" and displays the current price. The update method setsnex the price for stock "ABC" to 42.35. Now build and run the client by typing Axis2_HOME/samples/quickstartjibx directory.

"ant

run.client"

at

a

console

in

the

You should get the following as output: 42 done For more information on using JiBX with Axis2, see the JiBX code generation integration details.

Summary Axis2 is a slick and robust way to get web services up and running in no time. This guide presented five methods of creating a service deployable on Axis2, and four methods of creating a client to communicate with the services. You now have the flexibility to create Web services using a variety of different technologies.

For Further Study Apache Axis2: ●

http://ws.apache.org/axis2/

Axis2 Architecture: ●

http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html

Introduction to Apache Axis2: ●

http://www.redhat.com/magazine/021jul06/features/apache_axis2/

Working With Apache Axis2: ●

http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2

52

Apache Axis2 User's Guide This guide provides a starting place for users who are new to Apache Axis2. It also covers some advanced topics, such as how to use Axis2 to create and deploy Web services as well as how to use WSDL to generate both clients and services. For experienced users of Apache Axis2, we recommend the Advanced User's Guide.

Content •

Introducing Axis2 •

What is Axis2?



What's under the hood?



How Axis2 handles SOAP messages



Axis2 Distributions •

The Axis2 Standard Binary Distribution



Axis2.war Directory Hierarchy



Axis2 Documents Distribution



Axis2 and Clients



Installing and Testing Client Code



Introduction to Services •





Message Exchange Patterns

Creating Clients •

Choosing a Client Generation Method



Generating Clients



Axis Data Binding (ADB)

Building Services •

Getting Comfortable with Available Options



Creating a Service from Scratch



Deploying Plain Old Java Objects



Deploying and Running an Axis2 Service Created from WSDL



Samples



For Further Study

Introducing Axis2 This section introduces Axis2 and its structure, including an explanation of various directories/files included in the latest Axis2 download.

What is Axis2? The Apache Axis2 project is a Java-based implementation of both the client and server sides of the Web services equation. Designed to take advantage of the lessons learned from Apache Axis 1.0, Apache Axis2 provides a complete object model and a modular architecture that makes it easy to add functionality and support for new Web services-related specifications and

53

recommendations. Axis2 enables you to easily perform the following tasks: •

Send SOAP messages



Receive and process SOAP messages



Create a Web service out of a plain Java class



Create implementation classes for both the server and client using WSDL



Easily retrieve the WSDL for a service



Send and receive SOAP messages with attachments



Create or utilize a REST-based Web service

Create or utilize services that take advantage of the WS-Security, WSReliableMessaging, WS-Addressing, WS-Coordination, and WS-Atomic Transaction recommendations •

Use Axis2's modular structure to easily add support for new recommendations as they emerge •

Many more features exist as well, but this user guide concentrates on showing you how to accomplish the first five tasks on this list.

What's Under the Hood? To understand Axis2 and what it does, you must have a good idea of the life cycle of a Web services message. Typically, it looks something like this:

The sending application creates the original SOAP message, an XML message that consists of headers and a body. (For more information on SOAP, see "Introduction to Services".) If the system requires the use of WS* recommendations such as WS-Addressing or WS-Security, the message may undergo additional processing before it leaves the sender. Once the message is ready, it is sent via a particular transport such as HTTP, JMS, and so on. The message works its way over to the receiver, which takes in the message via the transport listener. (In other words, if the application doesn't have an HTTP listener running, it's not going to receive any HTTP messages.) Again, if the message is part of a system that requires the use of WS-Security or other recommendations, it may need additional processing for the purpose of checking credentials or decrypting sensitive information. Finally, a dispatcher determines the specific application (or other component, such as a Java method) for which the message was intended, and sends it to that component. That component is part of an overall application designed to work with the data being sent back and forth.

How Axis2 Handles SOAP Messages Axis2 can handle processing for both the sender and the receiver in a transaction. From the Axis2 perspective, the structure looks like this:

54

On each end, you have an application designed to deal with the (sent or received) messages. In the middle, you have Axis2, or rather, you can have Axis2. The value of Web services is that the sender and receiver (each of which can be either the server or the client) don't even have to be on the same platform, much less running the same application. Assuming that Axis2 is running on both sides, the process looks like this: •

The sender creates the SOAP message.

Axis "handlers" perform any necessary actions on that message such as encryption of WS-Security related messages. • •

The transport sender sends the message.



On the receiving end, the transport listener detects the message.



The transport listener passes the message on to any handlers on the receiving side.

Once the message has been processed in the "pre-dispatch" phase, it is handed off to the dispatchers, which pass it on to the appropriate application. •

In Axis2, these actions are broken down into "phases", with several pre-defined phases, such as the "pre-dispatch", "dispatch," and "message processing", being built into Axis2. Each phase is a collection of "handlers". Axis2 enables you to control what handlers go into which phases, and the order in which the handlers are executed within the phases. You can also add your own phases and handlers. Handlers come from "modules" that can be plugged into a running Axis2 system. These modules, such as Rampart, which provides an implementation of WS-Security, and Sandesha, which provides an implementation of WS-ReliableMessaging, are the main extensibility mechanisms in Axis2.

Axis2 Distributions Axis2 is released in several distributions. Which one you need depends on what you'll be doing with it.

The Axis2 Standard Binary Distribution If you're developing services and applications, you'll need the Axis2 Standard Binary Distribution. The distribution includes all the necessary *.jar files, as well as a variety of scripts that ease development. It has the following structure. Code Listing 1: Axis2 Standard Binary Distribution

55

bin

lib

axis2.bat axis2.sh axis2server.bat axis2server.sh java2wsdl.bat java2wsdl.sh wsdl2java.bat wsdl2java.sh setenv.sh

activation-1.1.jar ... XmlSchema.jar repository modules modules.list addressing-1.1.mar .. services services.list version.aar .. samples ... webapp ... conf axis2.xml LICENSE.txt README.txt NOTICE.txt INSTALL.txt release-notes.html The bin directory includes a number of useful scripts. They include axis2.bat (or axis2.sh), which enables you to easily execute a Java command without having to manually add all the Axis2 jar files to the classpath, java2wsdl.bat (and .sh) and wsdl2java.bat (and .sh), which enable you to easily generate Java code from a WSDL file and vice versa, and axis2server.bat (and sh), a simple Web server that enables you to build Axis2's capability to send and receive messages into your own application. As expected, the lib directory includes all the necessary .jar files. Services and modules are added to the repository directory. Axis2 comes with a standard module implementing WSAddressing, and you can add any other necessary module such as Rampart to the repository/modules directory. conf directory includes the axis2.xml which is the global deployment descriptor. Finally, the samples directory includes all the sample code distributed with Axis2. See the list of samples and their descriptions.

axis2.war Distribution Directory Hierarchy axis2.war is available in WAR (Web Archive) Distribution. The server side of Axis2 ships as a J2EE application, and has the following structure shown in Code Listing 2. Code Listing 2: Server Side of Axis2

56

axis2-web META-INF WEB-INF classes conf axis2.xml lib activation.jar ... xmlSchema.jar modules modules.list addressing.mar ... soapmonitor.mar services services.list aservice.aar ... version.aar web.xml Starting at the top, axis2-web is a collection of JSPs that make up the Axis2 administration application, through which you can perform any needed actions such as adding services and engaging and dis-engaging modules. The WEB-INF directory represents the actual Axis2 application, including all the *.jar files, any included modules, and even the deployed services themselves. The classes directory holds any class or property files that are needed by Axis2 itself, such as log4j.properties. Any actual services to be handled by the system reside in the services directory in the form of an axis archive, or *.aar file. This file contains any classes related to the service, as well as the services.xml file, which controls any additional requirements, such as the definition of message senders and message receivers. The main file in all this is axis2.xml, which controls how the application deals with received messages. It defines message receivers and transport receivers, as well as defining transport senders and determining which modules are active. It also defines the order of phases, and the handlers to be executed within each phase. You can control all of this information through the use of the Web application, but if you restart the Axis2 application, these changes are lost and the server goes back to the definitions in the axis2.xml file. Axis2 also provides a third distribution, the source distribution, which enables you to generate this .war file yourself.

Axis2 Documentation Distribution Directory Hierarchy The Documents distribution includes all Axis2 documentation including the xdcos and javadocs. It has the following structure: Code Listing 3: Axis2 Documents Distribution

57

docs javadocs xdocs LICENSE.txt README.txt release-notes.html The javadocs directory includes all the standard API documentation for the Axis2 API, with other documentation (like this document) in the xdocs directory.

Axis2 and Clients Now that explains how Axis2 behaves as part of a Web application. What about a standalone client that is not part of a J2EE application? In that case, a sender can use the Axis2 default properties, in other words, no special handlers, and so on. But you also have the option to tell the client to load its own copy of the axis2.xml file and behave accordingly.

Installing and Testing Client Code The best way to make sure that your system is running Apache Axis2 is to install and test both a service and a client. The process involves the following steps: The Short Story: 1. Install Apache Axis2 in a suitable container, such as Apache Tomcat, by copying the axis2.war file to the webapps directory. 2. Install the service into the Axis2 application by copying the *.aar file into the Axis2 services directory. 3. Install the client on the system on which you want to run it, and make sure all the Axis2 libraries are on the CLASSPATH. 4. Run the client. The Long Story: Start by installing a suitable container, such as Apache Tomcat. Any J2EE server will do. To install Apache Axis2 on the server, download the Axis2 WAR distribution from http://ws.apache.org/axis2/download.cgi and place the axis2.war file in the server's webapps directory. The server will then expand the distribution into its proper structure, as seen in the earlier section. Apache Axis2 services come bundled as *.aar files, which contain all the pieces necessary to define the service, such as the necessary classes and libraries and the services.xml file that defines the service's behavior. You can install the service using the Web administration application, but to make things simple for now, copy the *.aar file into the Axis2 services directory. For example, to install the MyService service distributed as one of the Axis2 samples, copy the file /samples/userguide/build/MyService.aar file, which is built using the ant command, from /samples/userguide, to the directory <J2EE_HOME>/webapps/axis2/WEB-INF/services. Your client can come in any number of forms, from a collection of files to a single *.jar file. The important thing is to ensure that all the appropriate classes are on the classpath. In addition to the classes that pertain to the actual client, you must also add the Axis2 .jar files into the CLASSPATH. Normally you will do this by downloading and unpacking the Axis2 Standard Distribution and adding the *.jar files in the lib directory to your CLASSPATH, or you also have the option of running your client using the axis2.bat (or axis2.sh) script, which takes care of it for you. For example, you can run a client with the command:

58

axis2 org.apache.axis2.axis2userguide.Client.

Introduction to Services The term "Web services" can apply to a number of different ways of sending information back and forth. However, this guide focuses on the sending and receiving of SOAP messages. SOAP messages are XML documents that consist of an "envelope" containing a "payload" (see Code Listing 4). Code Listing 4: Example SOAP Message <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/03/addressing"> <env:Header> <wsa:MessageID> http://ws.apache.org/9C21DE32-DB42-1228-C42E-66CB101421AD <wsa:ReplyTo> <wsa:Address>http://example.com/projects/clientApp <wsa:To>http://example.com/axis2/publishingService <wsa:Action>http://example.com/axis2/addDocument <env:Body> <docTitle>What I Did On My Summer Vacation <docSubtitle>Children's Essays from Accross the World <docLocation>contentRepos/summerVac.doc

This XML document consists of the outer element or the SOAP Envelope, and its contents. The SOAP Envelope is in the SOAP namespace, http://www.w3.org/2003/05/soap-envelope, prefixed as env: and contains up to two children. This envelope is a standard format that pertains to every single SOAP message sent and received by any SOAP Web service. The contents of the Envelope consists of two parts; the first being the SOAP headers-the contents of the env:Header element. These headers, such as the WS-Addressing elements shown here, provide additional information about the message and how it should be handled. A SOAP message may carry headers relating to several aspects of the message, or it may carry no headers at all. These headers are typically processed by the message handlers. The second and arguably the most important part of the message is the payload, which consists of the contents of the env:Body element. This is the actual message intended for the receiver, and it is the information that the main application will ultimately process.

Message Exchange Patterns Although all SOAP messages carry the same structure, the ways in which they are used can be combined into a number of different "message exchange patterns", or MEPs. The two major

59

message exchange patterns are: In-Out: in this MEP, the client sends a SOAP message to the server, which processes the message and sends a response back. This is probably the most commonly used MEP, and is useful for tasks such as searching for information or submitting information in situations in where acknowledgment is important. •

In-Only: In this MEP, the client sends a message to the server without expecting a response. You may use this MEP for activities such as pinging a server to wake it up, reporting logging information for which you do not need an acknowledgment and so on. •

Within these two MEPs, you also have several variables to consider: Blocking versus non-blocking: When the client sends a message, the application may wait to receive a response before moving on, or it may simply send a message and move on by specifying a callback action to be completed when the response is received. •

Number of parameters: Ultimately, a message sent from a client to server is intended to execute a particular action. That action may not require any parameters, or it may require one or more parameters. These parameters must be encoded as part of the payload of the message. •

Taking all these options into consideration, you can create virtually any MEP. For example, you can create an Out-Only system by reversing roles for the In-Only MEP. Apache Axis2 also includes support for less prominent MEPs, such as Robust-In-Only.

Creating Clients When it comes to creating a Web service client, you can do it manually (see Building Services), but in most cases you have a Web Service Description Language (WSDL) definition that describes the messages clients should send and expect to receive. Axis2 provides several ways to use this definition to automatically generate a client.

Choosing a Client Generation Method Axis2 gives you several options when it comes to mapping WSDL to objects when generating clients. Three of these options are Axis2 DataBinding Framework, XMLBeans, and JiBX databinding. All of these methods involve using databinding to create Java objects out of the XML structures used by the service, and each has its pros and cons. You can also generate XML in-out stubs that are not based on databinding. Axis2 Databinding Framework (ADB): ADB is probably the simplest method of generating an Axis2 client. In most cases, all of the pertinent classes are created as inner classes of a main stub class. ADB is very easy to use, but it does have limitations. It is not meant to be a full schema binding application, and has difficulty with structures such as XML Schema element extensions and restrictions. XMLBeans: Unlike ADB, XMLBeans is a fully functional schema compiler, so it doesn't carry the same limitations as ADB. It is, however, a bit more complicated to use than ADB. It generates a huge number of files, and the programming model, while being certainly usable, is not as straightforward as ADB. JiBX: JiBX is a complete databinding framework that actually provides not only WSDL-toJava conversion, as covered in this document, but also Java-to-XML conversion. In some ways, JiBX provides the best of both worlds. JiBX is extremely flexible, enabling you to choose the classes that represent your entities, but it can be complicated to set up. On the other hand, once it is set up, actually using the generated code is as easy as using ADB. In the end, for simple structures, ADB will likely be enough for you. If, on the other hand you need more power or flexibility, whether you choose XMLBeans or JiBX depends on how much power or flexibility you need and your tolerance for complexity.

60

Generating Clients The process for generating and using a client varies slightly depending on the method of generation you choose. In all three cases in this document, clients are generated from the same WSDL file (see Code Listing 5). Note that the document defines four operations, DoInOnly, NoParameters, TwoWayOneParameterEcho, and MultipleParametersAddItem. Each of the clients will include methods for calling each of these operations. (You can get more information on WSDL at http://www.w3.org/2002/ws/desc/ .)

Axis Data Binding (ADB) To create a client using ADB, execute the following steps: The short story: 1. href="http://ws.apache.org/axis2/download/1_2/download.cgi#std-bin" Download and unpack the Apache Axis2 Standard Distribution, if you have not done it already. 2. Create the client stub with the following command: %AXIS2_HOME%\bin\WSDL2Java -uri Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -d adb -s 3. Create the client (for example, Client.java), a Java application that uses the generated stub, and save it in the org/apache/axis2/axis2userguide directory. 4. Build the client by typing: ant jar.client. 5. Assuming you have a corresponding service, run the client by adding the generated Axis2UserGuideService-test-client.jar file located in build/lib to the classpath and type: java org.apache.axis2.axis2userguide.Client The long story: If you have not done it already, download and unpack the Apache Axis2 Standard Distribution. The Axis2 WAR Distribution does not include the necessary utilities for generating code, such as WSDL2Java. In the ADB method of generating clients, all the functionalities of the services are contained in a single class called a stub. The stub contains inner classes corresponding to all the necessary objects defined in the WSDL file, such as, in the case of this WSDL, DoInOnlyRequestMessage. Once you have the stub, you will be able to create a client by simply referring to these classes and their methods. To generate the client, issue the following command in Code Listing 6. Code Listing 6 - Generating the Client %AXIS2_HOME%\bin\WSDL2Java -uri Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -d adb -s This command analyzes the WSDL file and creates the stub in the package org.apache.axis2.axis2userguide. The options specify that you want the ADB data binding method (-d), and synchronous or blocking, methods (-s). In other words, when the client makes an In-Out call to the service, it will wait for a response before continuing. Once you run this command, you will see two new items in the directory. The first is the build.xml file, which contains the instructions for Ant to compile the generated classes. The second is the src directory, which contains the actual Axis2UserGuideServiceStub.java file. If you open this file, you will see a collection of inner classes for each of the items in the WSDL file. You'll also see a number of calls to the Axis2 client API, including those that use AXIOM to build and analyze the incoming and outgoing messages. Now you need a client to make use of this code. To create a client, create a new class and

61

save it as Client.java in the org/apache/axis2/axis2userguide directory. It should contain the following code in Code Listing 7. Note that using the service is simply a matter of creating and populating the appropriate type of request using the names defined in the WSDL file, and then using the stub to actually send the request to the appropriate method. For example, to call the DoInOnly operation, you create a DoInOnlyRequest, use its setMessageString() method to set the contents of its messageString element, and pass it as an argument to stub.DoInOnly(). To build the client, type: ant jar.client This action creates two new directories, build and test. The test directory will be empty, but the build directory contains two versions of the client. The first version, in the lib directory, is a .jar file that contains the client class and the stub. The second, in the classes directory, is just raw classes. Make sure all the jar files in the Axis2 lib directory are in the classpath. If you have a service corresponding to this client you can run the client by adding the jar file to your classpath and typing: java org.apache.axis2.axis2userguide.Client (If you don't have such a service,, refer to the Building services document.) You should see the response in the console window of your servlet container. It should look something like this:

ADB is not your only option for generating Web service clients. Other options include XmlBeans, JiBX, JAXME and JAXBRI.

Building Services Now that you know how to use Axis2 to generate clients from WSDL, this section digs a little deeper showing you how to create services, and also how to create services and clients "from scratch", so to speak.

Getting Comfortable with the Available Options Axis2 provides a number of ways to create a service, such as: Create a service and build it from scratch. In this case, you build your service class to specifically access AXIOM OMElement objects, then create the services.xml file and •

62

package it for deployment. •

Deploy Plain Old Java Objects (POJOs) as a service.

Generate the service from WSDL. Just as you can generate clients with WSDL, you can also generate the skeleton of a service. •

Let's look at these three options.

Creating a Service from Scratch Creating a service from scratch is not the most convenient way to do it, but it does give you the most control. The process involves several steps. The short story: 1. Create the service class with each operation that is represented by a method that takes an org.apache.axiom.om.OMElement object as its argument. (An OMElement is how the AXIs2 Object Model (AXIOM) represents an XML element.) 2. Create the service descriptor, services.xml, which defines the class to be used by the service and the appropriate message receivers. 3. Create the .aar file, with the classes in their proper locations based on the package and the services.xml file in the META-INF directory. 4. Deploy the .aar file by using the Web Administration application or by copying it to the Axis2 services directory. The long story: Start by creating the service class, a plain Java class that uses classes from the Axis2 libraries (see Code Listing 8). Code Listing 8-Creating the Service Class

63

package org.apache.axis2.axis2userguide; import import import import import

javax.xml.stream.XMLStreamException; org.apache.axiom.om.OMAbstractFactory; org.apache.axiom.om.OMElement; org.apache.axiom.om.OMFactory; org.apache.axiom.om.OMNamespace;

public class SampleService { public OMElement sayHello(OMElement element) throws XMLStreamException { element.build(); element.detach(); String rootName = element.getLocalName(); System.out.println("Reading "+rootName+" element"); OMElement childElement = element.getFirstElement(); String personToGreet = childElement.getText(); OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://example1.org/example1", "example1"); OMElement method = fac.createOMElement("sayHelloResponse", omNs);

OMElement value = fac.createOMElement("greeting", omNs); value.addChild(fac.createOMText(value, "Hello, "+personToGreet)); method.addChild(value); }

return method;

private void ping(){ } }

Make sure to include Axis2 libraries in your class path when compiling the source. Axis2 uses AXIOM, or the AXIs Object Model, a DOM (Document Object Model) -like structure that is based on the StAX API ( Streaming API for XML). Methods that act as services must take an OMElement as their argument, which represents the payload of the incoming SOAP message. (An OMElement is just AXIOM's way of representing an XML element, like a DOM Element object.) In this case, you're extracting the contents of the first child of the payload element, adding text to it, and using it as content for the return OMElement. Unless this is an "in only" service, these methods must return an OMElement, because that becomes the payload of the return SOAP message. To turn this class into a service, create the service description file, services.xml, as in Code Listing 9. Code Listing 9 - Create the Service Description

64

<service name="UserGuideSampleService"> <description> This is a sample service created in the Axis2 User's Guide <parameter name="ServiceClass" locked="false">org.apache.axis2.axis2userguide.SampleService <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> This document defines the service, called by the Web Administration Application, and the class used to serve requests. For each operation, it defines the appropriate message receiver class. Create a new directory, META-INF, in the main directory for the class. (In this case, that's the same directory that contains the org directory) and place the services.xml file in it. Create the .aar file by typing: jar cvf SampleService.aar ./* Deploy the SampleService.aar file by using the Web Administration application or by copying it to the Axis2 services directory. Now you can create a client class that accesses the service directly (see Code Listing 10). Code Listing 10 - Create a Client Class that Accesses the Service Directly

65

package org.apache.axis2.axis2userguide; import import import import import import import import import

javax.xml.stream.XMLStreamException; org.apache.axiom.om.OMAbstractFactory; org.apache.axiom.om.OMElement; org.apache.axiom.om.OMFactory; org.apache.axiom.om.OMNamespace; org.apache.axis2.addressing.EndpointReference; org.apache.axis2.client.Options; org.apache.axis2.Constants; org.apache.axis2.client.ServiceClient;

public class SampleClient { private static EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/UserGuideSampleServ ice"); public static OMElement greetUserPayload(String personToGreet) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://example1.org/example1", "example1"); OMElement method = fac.createOMElement("sayHello", omNs); OMElement value = fac.createOMElement("personToGreet", omNs);

value.addChild(fac.createOMText(value, personToGreet)); method.addChild(value); return method; }

public static void main(String[] args) { try { OMElement payload = SampleClient.greetUserPayload("John"); Options options = new Options(); options.setTo(targetEPR); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); ServiceClient sender = new ServiceClient(); sender.setOptions(options); OMElement result = sender.sendReceive(payload); String response = result.getFirstElement().getText(); System.out.println(response);

}

} catch (Exception e) { //(XMLStreamException e) { System.out.println(e.toString()); }

} This class uses the same technique of sending and receiving OMElements, but it's also important to note the use of the Options class. This class enables you to determine properties such as the transport used for the return message (the transport used for the outgoing message can be inferred from the URL of the destination) and the SOAP version to use. In addition to providing setter and getter methods of specific properties that affect how the client interacts with the service, the Options class enables you to create inheritance relationships

66

between Options objects. So if a property is not found in the current Options object used, the client can check the parent Options object of the current Options object. Compile and run the above SampleClient.java. Make sure to have all axis2 libraries in your class path. If all has gone well, 'Hello, John' will be shown as the output in the console.

Deploying Plain Old Java Objects (POJOs) One very easy way to create a Web service is simply to deploy the Java objects that represent the service. Start with the class, shown in Code Listing 11. Code Listing 11 - Creating the Class SampleService package org.apache.axis2.axis2userguide; public class SampleService { public void doInOnly(){ return; } public String noParameters(){ return "Hello"; } public String twoWayOneParameterEcho(String toEcho){ return toEcho; } public boolean multipleParametersAdd(float price, int itemId, String description, String itemName){ //Code to handle the logic return true; } } Next, you'll need to tell Axis2 what class corresponds with what Web service calls. Do this by creating a file called services.xml and adding the following shown in Code Listing 12. Code Listing 12 - Creating services.xml <service name="SampleService" scope="application"> <description> Sample Service <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass"> org.apache.axis2.axis2userguide.SampleService

This file makes the InOnly and InOut MEPs available to the service and tells Axis2 which class to call; operations must match method names. In other words, Axis2 automatically sends a call to the multipleParametersAdd operation to the org.apache.axis2.axis2userguide.SampleService.multipleParametersAdd() method.

67

Now it's time to create the distribution. Arrange your files in the following directory structure (see Code Listing 13). Code Listing 13- Create the Directory Structure for the Distribution - SampleService - META-INF - services.xml - org - apache - axis2 - axis2userguide - SampleService.class Finally, deploy the service by copying the SampleService directory to the webapps/axis2/WEB-INF/services directory on the servlet engine. You can check to make sure that it's been properly deployed by checking http://:<port>/axis2/services/listServices.

Deploying and Running an Axis2 Service Created from WSDL If you have a WSDL file, you can easily create and deploy a service based on that description. For example, to create a service based on the same WSDL file used in the clients section of this document, you will follow the steps below. The short story: 1. Download the Axis2 standard distribution, if you have not done so already. 2. Generate the skeleton using the WSDL2Java utility, as in: java org.apache.axis2.wsdl.WSDL2Java file:///C:/apps/axis2/samples/zSample/Axis2UserGuide.wsdl org.apache.axis2.axis2userguide -d adb -s -wv 1.1 -ss -sd -ssi

-uri -p

3. Open the *Skeleton.java file and add the functionality of your service to the generated methods. 4. Build a service using Ant by typing ant jar.server 5. Deploy the service by copying <J2EE_HOME>/webapps/axis2/WEB-INF/services

the

build/lib/*.aar

file

to

6. Check http://<server>:<port>/axis2/services/listServices to make sure the service has been properly deployed. The long story: As with generating clients, you will need the Axis2 Standard Distribution, because the Axis2 WAR Distribution does not include the WSDL2Java utility. Once you've got it downloaded and unpacked, make sure that you set the AXIS2_HOME variable to point to the location in which you've unpacked it. Now you are ready to generate the actual service. To keep things neat, create a new directory and change to it. The WSDL file is the same one referenced in Generating Clients and includes four operations: NoParameters, TwoWayOneParameterEcho, MultipleParametersAddItem, and DoInOnly. To generate the service, use the WSDL2Java utility, as in Code Listing 14.

Code Listing 14 - Using the WSDL2Java Utility to Generate the Service Code Listing 14.1:

68

java org.apache.axis2.wsdl.WSDL2Java -uri file:///C:/apps/axis2/samples/zSample/Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -d adb -s -wv 1.2 -ss -sd Note: Make sure all the .jar files in the Axis2 lib directory is set to the CLASSPATH before you run the above code. This statement tells the utility you want to create a service out of the operations in the file Axis2UserGuide.wsdl, and that the Java classes generated should be in the org.apache.axis2.axis2userguide package (-p). (You can view the appropriate directories created.) It also indicates that you want to use the Axis2 DataBinding Framework, or ADB (-d), to generate only synchronous or blocking code (-s), and to generate server-side code (-ss) as opposed to a client, including the services.xml service descriptor file (-sd). It also specifies version 1.2 for the WSDL file (-wv). Code Listing 14.2: You can also use the following script files to achieve the same. In this case you do not have the set the CLASSPATH manually. For Linux: $AXIS2_HOME/bin/wsdl2java.sh -uri file:///C:/apps/axis2/samples/zSample/Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -o target_directory_name -d adb -s -wv 1.2 -ss -sd For MS Windows: %AXIS2_HOME%\bin\wsdl2java.bat -uri file:\\\C:\apps\axis2\samples\zSample\Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -o target_directory_name -d adb -s -wv 1.2 -ss -sd In both instances, at this point, you should see four new items in your chosen directory: the build.xml file, which includes instructions for Ant, the src directory, which includes all the generated classes and stubs, the resources directory, which includes a regenerated version of the WSDL, and the services.xml file, which ultimately controls the service's behavior. You can compile the service at this point, but it doesn't actually do anything yet. You can solve that problem by opening the src\org\apache\axis2\axis2userguide\Axis2UserGuideServiceSkeleton.java file and either editing the code in bold -- make sure you manage parameter numbers -- or replacing all the code with the following in Code Listing 15.

69

Code Listing 15 - Compiling the Service /** * Axis2UserGuideServiceSkeleton.java * This file was auto-generated from WSDL * by the Apache Axis2 version: SNAPSHOT Oct 15, 2006 (11:23:18 GMT+00:00) */ package org.apache.axis2.axis2userguide; /** * Axis2UserGuideServiceSkeleton java skeleton for the axisService */ public class Axis2UserGuideServiceSkeleton { /** * Auto generated method signature * @param param7 */ public org.apache.axis2.axis2userguide.NoParametersResponse NoParameters (org.apache.axis2.axis2userguide.NoParametersRequest param7) { System.out.println(param7); NoParametersResponse res = new NoParametersResponse(); return res; } /** * Auto generated method signature * @param param9 */ public org.apache.axis2.axis2userguide.TwoWayOneParameterEchoResponse TwoWayOneParameterEcho ( org.apache.axis2.axis2userguide.TwoWayOneParameterEchoRequest param9 ) { System.out.println(param9.getEchoString()); TwoWayOneParameterEchoResponse res = new TwoWayOneParameterEchoResponse(); res.setEchoString(param9.getEchoString()); return res; }

70

/** * Auto generated method signature * @param param11 */ public void DoInOnly ( org.apache.axis2.axis2userguide.DoInOnlyRequest param11 ) { System.out.println(param11.getMessageString());

}

/** * Auto generated method signature * @param param12 */ public org.apache.axis2.axis2userguide.MultipleParametersAddItemResponse MultipleParametersAddItem ( org.apache.axis2.axis2userguide.MultipleParametersAddItemRequest param12 ) { System.out.println(param12.getPrice()); System.out.println(param12.getItemId()); System.out.println(param12.getDescription()); System.out.println(param12.getItemName()); MultipleParametersAddItemResponse res = new MultipleParametersAddItemResponse(); res.setSuccessfulAdd(true); res.setItemId(param12.getItemId()); return res; } }

As with generating clients, all these classes, such as MultipleParametersAddItemRequest and TwoWayOneParameterEchoResponse, are generated by the utility, and can be found in the same directory as the skeleton file. They include methods such as setSuccessfulAdd(), which sets the value of the content of an element in the response, and getItemName(), which retrieves the content of elements in the request. Save the file and compile it by typing: ant jar.server If all goes well, you should see the BUILD SUCCESSFUL message in your window, and the Axis2UserGuideService.aar file in the newly created build/lib directory.

71

Now you need to deploy the service to the server. To do that, copy the Axis2UserGuideService.aar file to the WEB-INF/services directory of the application server. (You also have the option to use the administration tools. See the Web Administrator's Guide for more information.) To verify that the service has been properly deployed, check the list of services at http://:<port>/axis2/services/listServices.

Now you should be able to access the service using any of the clients built in the Generating Clients document.

72

The Samples The Apache Axis2 Standard Distribution provides a number of samples you can use as a guide for implementing specific features and capabilities. These services are listed in this section.

Clients (in AXIS2_HOME/samples/userguide/src/clients): EchoBlockingClient.java: A basic example of the send/receive MEP. EchoBlockingDualClient.java: Specifies that the return message should be sent over a different channel than the request message. EchoBlockingWsaBasedClient.java: Provides an example of using the capabilities of WSAddressing action mapping. EchoNonBlockingClient.java: Demonstrates an asynchronous request using Callbacks. EchoNonBlockingDualClient.java: Similar to the above, but uses a separate listener for the response. ClientForWebServiceWithModule.java: Simply makes a call to a service with engaged modules. ClientSideModuleEngagement.java: Demonstrates the use of modules on the client side, in addition to the server side. MailClient.java: Demonstrates the use of the Robust In-Only MEP. PingClient.java: A simple "fire and forget" client. RESTClient.java: Demonstrates the ability to request a REST response rather than a SOAP response. Also demonstrates setting arbitrary properties on the Options object. TCPClient.java: Provides an example of using the TCP transport rather than HTTP.

Services (in AXIS2_HOME/samples/userguide): groovyService.aar: Demonstrates how to use Groovy classes in the processing of SOAP messages. MyService.aar: Provides simple "echo" and "ping" operations. MyServiceWithModule.aar: Same as above, but demonstrates how to engage a module. WsaMappingService.aar: Demonstrates the mapping of WS-Addressing actions.

Sample WSDL files (in AXIS2_HOME/samples): Axis2SampleDocLit.wsdl: Demonstrates the use of the Document/Literal WSDL pattern, rather than RPC. perf.wsdl: Demonstrates the use of array values as input values.

Other samples In AXIS2_HOME/samples Directory: faulthandling: Demonstrates the use of SOAP faults and their definitions in WSDL enabling exception processing in the client. googleSpellcheck: Demonstrates both synchronous and non-synchronous use of the

73

Google Web Service in a GUI. mtom: Demonstrates the use of MTOM and SOAP with Attachments to send binary files to a service. saopwithattachments: Demonstrates the capabilities and power of SOAP with Attachment support and the Attachment API of Axis2. pojo: Example of a POJO (Plain Old Java Object) Web service. It shows how to expose the methods of a Java class as a Web service using Apache Aixs2. servicelifecycle: Demonstrates the usage of a service life cycle and a bit of session management. The main idea is to show where and how to use the service life cycle interface and session related methods. databinding: Demonstrates how to use WSDL2Java generated code with Castor. version: A very simple service that simply outputs the Apache Axis2 version. yahoorestearch: A complete example of the use of a REST service rather than a SOAP service.

External: FlickrClient : Demonstrates code generation capabilities for WSDL 2.0. The FlickrService.wsdl describes services offered by flickr in terms of WSDL 2.0. It also demonstrates how a restful service can be described using the HTTPBinding of wsdl 2.0. Extract the WSO2 WSAS for Java nightly build distribution and you will find the sample at WSAS_HOME/samples/FlickrClient or checkout sample from SVN: http://wso2.org/repos/wso2/trunk/wsas/java/modules/samples/FlickrClient

For Further Study Resources Axis2 Architecture: ●

http://ws.apache.org/axis2/1_2/Axis2ArchitectureGuide.html

XML processing with AXIOM: ●

http://ws.apache.org/commons/axiom/OMTutorial.html

RESTful Web Services: ●

http://ws.apache.org/axis2/1_2/rest-ws.html

TCP Transport: ●

http://ws.apache.org/axis2/1_2/tcp-transport.html

Mail Transport: ●

http://ws.apache.org/axis2/1_2/mail-transport.html

HTTP Transports: ●

http://ws.apache.org/axis2/1_2/http-transport.html

MTOM with Axis2: ●

http://ws.apache.org/axis2/1_2/mtom-guide.html

Securing SOAP Messages with Apache Rampart: ●

http://ws.apache.org/axis2/modules/rampart/1_2/security-module.html

74

SOAPMonitor: ●

http://ws.apache.org/axis2/1_2/soapmonitor-module.html

Apache Axis2 Advance User's Guide: ●

http://ws.apache.org/axis2/1_2/adv-userguide.html

Apache Axis2 Advanced User's Guide This guide will help you get started with Axis2, the next generation of Apache Axis! It gives a detail description on how to write Web services and Web service clients using Axis2, how to write custom modules, and how to use them with a Web service. Advanced Topics and Samples that are shipped with the binary distribution of Axis2, are also discussed.

Introduction This user guide is written based on Axis2 Standard Binary Distribution. The Standard Binary Distribution can be directly downloaded or built using the Source Distribution. If you choose the latter, then the Installation Guide will instruct you on how to build Axis2 Standard Binary Distribution using the source. Please note that Axis2 is an open-source effort. If you feel the code could use some new features or fixes, please get involved and lend us a hand! The Axis developer community welcomes your participation. Let us know what you think! Send your feedback to "[email protected]". (Subscription details are available on the Axis2 site.) Kindly prefix the subject of the mail with [Axis2].

Getting Started The first two sections of the user guide explain how to write and deploy a new Web Service using Axis2, and how to write a Web Service client using Axis2. The next section - Configuring Axis2 - provides an introduction to important configuration options in Axis2. The final section Advanced Topics - provides references to other features In this (first) section, we will learn how to write and deploy Web services using Axis2. All the samples mentioned in this guide are located in the "samples/userguide/src" directory of Axis2 standard binary distribution. Please deploy axis2.war in your servlet container and ensure that it works fine. The Installation Guide gives you step-by-step instructions on just how to build axis2.war and deploy it in your servlet container.

Creating a New Web Service If you are interested in how to write a Web Service client using Axis2, it is decribed under Writing a Web Service Client. Axis2 provides two ways to create new Web Services, using code generation and using XML based primary APIs. The following section explains how to start from a WSDL, and create a new service with code generation. For the XML based primary API, please refer to the section Writing Web Services Using Axis2's Primary APIs for more information. However, if you are a new user, it is better to follow the code generation approach first (given below)

Starting with WSDL, Creating and Deploying a Service We start with a WSDL, however if you do not have a WSDL and need to create a WSDL from

75

a java class, please use the Java2WSDL tool and create a WSDL. As you might already know, a WSDL description of a service provides a precise definition of a Web Service. Axis2 can process the WSDL and generate java code that does most of the work for you. At the server side, we call them Skeletons, and at the client side, Stubs. This method of writing a Web service with Axis2 involves four steps: 1. Generate the skeleton code. 2. Add business logic. 3. Create a *.aar archive (Axis Archive) for the Web service. 4. Deploy the Web service.

Step1: Generate Skeleton Code To generate the skeleton and required classes, you can use the WSDL2Java tool provided in Axis2. This tool is located in the bin directory of the distribution and can be executed using the provided scripts (.bat or .sh). The tool's parameter list can be found in the Axis2 Reference Document. The parameters for the wsdl2java tool in our example are as follows. Please note that we use xmlbeans as the data binding framework, and generated code will be sent to the samples directory. Other data binding tools you can use are adb (Axis data binding) and jaxme (JaxMe data binding) wsdl2java.sh -uri ../samples/wsdl/Axis2SampleDocLit.wsdl -ss -sd -d xmlbeans -o ../samples -p org.apache.axis2.userguide This will generate the required classes in the "sample/src" directory, and the schema classes in the "samples/resources/schemaorg_apache_xmlbeans" directory. Note that these are not source files and should be available in the class path in order to compile the generated classes.

Step 2: Implement Business Logic Now you should fill the business logic in the skeleton class. You can find the skeleton class -Axis2SampleDocLitServiceSkeleton.javaamong the generated classes in the "samples/src/org/apache/axis2/userguide directory. Let's fill the echoString(..) method in the skeleton as shown below. Our sample WSDL-Axis2SampleDocLit.wsdl in "samples/wsdl" directory has three operations: echoString, echoStringArray, echoStruct. To see how the others will look when they are filled up, see Code Listing For Axis2SampleDocLitService Service

public org.apache.axis2.userguide.xsd.EchoStringReturnDocument echoString(org.apache.axis2.userguide.xsd.EchoStringParamDocument param4) throws Exception { //Use the factory to create the output document. org.apache.axis2.userguide.xsd.EchoStringReturnDocument retDoc = org.apache.axis2.userguide.xsd.EchoStringReturnDocument.Facto ry.newInstance(); //send the string back. retDoc.setEchoStringReturn(param4.getEchoStringParam()); return retDoc;

Step 3: Create Archive File An Axis2 service must be bundled as a service archive. The next step is to package the

76

classes in an .aar (axis2 archive) and deploy it in Axis2. There is an ant file generated with the code; it will generate the Axis2 service archive for you. However, if you do not want to use ant, you can create an archive with the following steps : 1. Compile the generated code. 2. Copy "resources/schemaorg_apache_xmlbeans" xmlbeans classes to your class folder. 3. Among the generated files, there will be a services.xml file, which is the deployment descriptor for Axis2 service.[learn more about it]. Copy the resources/service.xml to META-INF/services.xml (To write your own service.xml file, see the sub section in Writing Web Services Using Axis2's Primary APIs ) 4. Create the archive using content of the class folder. Change the directory to the class folder and run jar -cf <service-name>.aar to create the archive. Once the archive is created, the content of the JAR should look like this.

Step 4: Deploy Web Service The service can be deployed by simply dropping the ".aar" file into the "services" directory in "/webapps/axis2/WEB-INF" of your servlet container. We recommend using Apache Tomcat as the servlet container. Please Note that the services directory is available only after axis2.war is exploded by Tomcat. However, the easiest way to do it is to start Tomcat after axis2.war is copied to the webapps directory (if you have not already started). Check the "Services" link on the Home page of Axis2 Web Application (http://localhost:8080/axis2) and see whether the Axis2SampleDocLitService is displayed under the deployed services. We recommend using the exploded configuration to deploy Axis2 WAR in WebLogic and WebSphere application servers to support the hotupdate/ hotdeployment features in Axis2. See Application Server Specific Configuration Guide for details. Note: Axis2 provides an easy way to deploy Web Services using the "Upload Service" tool in the Axis2 Web Application's Administration module. (See the Web Administration Guide for more information)

Writing a Web Service Client Axis2 also provides a more complex, yet powerful XML based client API which is intended for advanced users. Read Writing Web Service Clients Using Axis2's Primary APIs to learn more about it. However, if you are a new user, we recommend using the code generation approach presented below.

Generate Stubs Let's see how we could generate java code (Stub) to handle the client side Web Service invocation for you. This can be done by running the WSDL2Java tool using the following

77

arguments wsdl2java.sh -uri ../samples/wsdl/Axis2SampleDocLit.wsdl -d xmlbeans -o ../samples/src -p org.apache.axis2.userguide This will generate client side stubs and xmlbeans types for your types. The Stub class that you need to use will be of the form <service-name>Stub. In our example, it will be called "Axis2SampleDocLitServiceStub.java" Axis2 clients can invoke Web Services both in a blocking and non-blocking manner. In a blocking invocation, the client waits till the service performs its task without proceeding to the next step. Normally, the client waits till the response to the particular request arrives. In a non-blocking invocation, the client proceeds to the next step immediately, and the responses (if any) are handled using a Callback mechanism. Please note that some explanations use the terms Synchronous and Asynchronous to describe the similar invocation strategies.

Do a Blocking Invocation The following code fragment shows the necessary code calling echoString operation of the Axis2SampleDocLitService that we have already deployed. The code is extremely simple to understand and the explanations are in the form of comments. try { org.apache.axis2.userguide.Axis2SampleDocLitServiceStub stub = new org.apache.axis2.userguide.Axis2SampleDocLitServiceStub(null, "http://localhost:8080/axis2/services/Axis2SampleDocLitService"); //Create the request document to be sent. org.apache.axis2.userguide.xsd.EchoStringParamDocument reqDoc = org.apache.axis2.userguide.xsd.EchoStringParamDocument.Factory.newIn stance(); reqDoc.setEchoStringParam("Axis2 Echo"); //invokes the Web service. org.apache.axis2.userguide.xsd.EchoStringReturnDocument resDoc = stub.echoString(reqDoc); System.out.println(resDoc.getEchoStringReturn()); } catch (java.rmi.RemoteException e) { e.printStackTrace(); }

First argument of Axis2SampleDocLitPortTypeStub should be the Axis2 repository for the client. Here we use null to make the stub use default configurations. However, you can make Axis2 use your own repository by providing it here. You can find more information about this from the Axis2 Configuration section. You can find code to invoke other operations from Code Listing For Axis2SampleDocLitService Service

Do a Non-Blocking Invocation The stubs also include a method that allows you to do a non-blocking innovation. For each method in the Service, there will be a method start<method-name>. These methods accept a callback object, which would be called when the response is received. Sample code that does an asynchronous interaction is given below.

78

try { org.apache.axis2.userguide.Axis2SampleDocLitServiceStub stub = new org.apache.axis2.userguide.Axis2SampleDocLitServiceStub(null, "http://localhost:8080/axis2/services/Axis2SampleDocLitServ ice"); //implementing the callback online org.apache.axis2.userguide.Axis2SampleDocLitServiceCallbackH andler callback = new org.apache.axis2.userguide.Axis2SampleDocLitServiceCallbackHandler() { public void receiveResultechoString( org.apache.axis2.userguide.xsd.EchoStringReturnDoc ument resDoc) { System.out.println(resDoc.getEchoStringReturn()); } }; org.apache.axis2.userguide.xsd.EchoStringParamDocument reqDoc = org.apache.axis2.userguide.xsd.EchoStringParamDocument.Factory .newInstance(); reqDoc.setEchoStringParam("Axis2 Echo"); stub.startechoString(reqDoc, callback); } catch (java.rmi.RemoteException e) { e.printStackTrace(); }

Even though the above code does a non-blocking invocation at the client API, the transport connection may still operate in a blocking fashion. For example, a single HTTP connection can be used to create a Web Service request and to get the response when a blocking invocation happens at the transport level. To perform a "true" non-blocking invocation in which two separate transport connections are used for the request and the response, please add the following code segment after creating the stub. It will force Axis2 to use two transport connections for the request and the response while the client uses a Callback to process the response. stub._getServiceClient().engageModule(new QName("addressing")); stub._getServiceClient().getOptions().setUseSeparateListener(true); Once those options are set, Axis2 client does the following: 1. Starts a new Transport Listener(Server) at the client side. 2. Sets the address of the Transport Listener, as the ReplyTo WS-Addressing Header of the request message 3. According to the WS-Addressing rules, the Server will process the request message and send the response back to the ReplyTo address. 4. Client accepts the response, processes it and invokes the callback with the response parameters.

Using Your Own Repository You could use your own repository with Axis2 Client, code below shows how to do this.

79

String axis2Repo = ... String axis2xml = ... ConfigurationContext configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(axi s2Repo, axis2xml); Service1Stub stub1 = new Service1Stub(configContext,...); //invoke Service1 Service2Stub stub2 = new Service2Stub(configContext,...); //invoke Service2

Note by creating the ConfigurationContext outside and passing it to the stubs, you could make number of stubs to use same repository, thus saving the configuration loading overhead from each request.

Configuring Axis2 Axis2 Repository Axis2 configuration is based on a repository and standard archive format. A repository is a directory in the file system, and it should have the following: 1. axis2.xml, the Axis2 global deployment descriptor in conf/axis2.xml file 2. services directory, which will have the service archives 3. modules directory (optional), which will have the module archives Both services and modules will be identified and deployed once their archives are copied to the corresponding directories. At the server side, users should specify the repository folder at the time of starting the Axis2 Server (e.g. HTTP or TCP). In Tomcat, webapps/axis2/WEB-INF folder acts as the repository. At the client side, binary distribution can itself be a repository. You can copy the conf directory which includes the axis2.xml file from the exploded axis2.war and edit it to change the global configurations repository.

Global Configurations The Global configuration can be changed by editing the axis2.xml file, refer to the Axis2 Configuration Guide for more information.

Add New Services New services can be written either using WSDL based code generation as we did, or from scratch as explained in Writing Web Services Using Axis2's Primary APIs. Read Creating a Service from Scratch for more information. Also refer to Axis2 Configuration Guide for a reference on services.xml file.

Engaging Modules Each module(.mar file) provides extensions to Axis2. A module can be deployed by copying it to the modules directory in the repository. Then it becomes available and can be engaged at a global, service or operation scope. Once engaged, it becomes active (adds handlers to the execution flow) at the respective scope. Please refer to Axis2 architecture guide for detailed explanation. The following table explains the semantics of scope, and how to engage modules in those scopes.

80

Scope

Semantics Add handlers in the module to all the services. Addressing Handler can be only engaged as global

Global

How to Engage

By adding a <module ref="addressing"/> to the Axis2 xml file or calling stub._getServiceClient().engageModule(moduleName)

at client side

Add handlers in the module to a specific service

By adding a <module ref="addressing"/> to a service.xml file in a service archive

Add handlers in the Operation module to a specific operation

By adding a <module ref="addressing"/> inside an operation tag of a service.xml file in a service archive

Service

* If a handler is added to a service or an operation, it will be invoked for every request received by that service or operation Axis2 provides a number of built in Modules (such as addressing,Security, WS-Reliable Messaging), and they can be engaged as shown above. Please refer to each module on how to use and configure them. You can also create your own modules with Axis2. Also refer to Axis2 Configuration Guide for a reference on the module.xml file.

WS-Addressing Support WS-Addressing support for Axis2 is implemented by the addressing module. To enable addressing, you need to engage the addressing module in both server and client sides. 1. To enable addressing at the server side, you need to copy the addressing.mar file to the modules directory of the server's axis2 repository. To engage the module, add a <module ref="addressing"/> to axis2.xml. The Addressing module can be engaged only at global level. 2. To enable addressing at the client side, you should add it to the repository and provide the repository as an argument to the ServiceClient or generated stub or have it in your classpath. 3. To engage the addressing module, you should either ref="addressing"/> to the axis2.xml file at the client side or call stub._getServiceClient().engageModule(moduleName)

add

<module

Advanced Topics Transports By default, Axis2 is configured to use HTTP as the transport. However, Axis2 supports HTTP, SMTP, TCP and JMS transports. You can also write your own transports, and deploy them by adding new transportReceiver or transportSender tags to axis2.xml. To learn how to configure and use different transports, please refer to the following documents. 1. TCP Transport 2. Mail Transport 3. HTTP Transports 4. JMS Transports

81

Attachments Axis2 provides attachment support using MTOM. Please refer to MTOM with Axis2 for more information.

Security Axis2 provides Security support using Apache Rampart. Please refer to Securing SOAP Messages with Apache Rampart for more information.

REST Web Service Please refer to RESTful Web Services for more information.

Pluggable Data Binding Axis2 ships with Axis Data Binding(ADB) as the default data binding framework. However, data binding frameworks are pluggable to Axis2, and therefore you can use other data binding frameworks with Axis2. Please refer to the following documents for more information.

Axis2 Data Binding(ADB) 1. Axis2 Databinding Framework 2. ADB Integration With Axis2 3. Advanced Axis2 Databinding Framework Features 4. ADB Tweaking Guide

JiBX JiBX Integration With Axis2

Other Topics 1. Axis2 Integration With The Spring Framework 2. Web Services Policy Support In Axis2 3. Axis2 Configuration Guide 4. Axis2 RPC Support 5. Migrating from Apache Axis 1.x to Axis 2 6. Writing your Own Axis2 Module 7. Using the SOAP Monitor 8. Writing Web Services Using Axis2's Primary APIs 9. Writing Web Service Clients Using Axis2's Primary APIs 10.Application Server Specific Configuration Guide

Axis2 Configuration Guide In Axis2, there are three kinds of configuration files to configure the system. The first one is to configure the whole system (global configuration), the second one is to configure a service

82

(service configuration), and the third one is to configure a module (module configuration). This document explains the above configurations in detail.

Content •

Global Configuration (axis2.xml)



Service Configuration (services.xml)



Module Configuration (module.xml)

Global Configuration •

Writing axis2.xml

All the configurations that require starting Axis2 are obtained from axis2.xml. The way to specify them is extremely simple and easy. The document is all about the proper way of specifying the configurations in axis2.xml. There are six top level elements that can be seen in the configuration file and can be listed as follows: •

Parameter



Transport Receiver



Transport Sender



Phase Order



Module References



Listeners (Observers)

Parameter In Axis2, a parameter is nothing but a name value pair. Each and every top level parameter available in the axis2.xml (direct sub elements of the root element) will be transformed into properties in AxisConfiguration. Therefore, the top level parameters in the configuration document can be accessed via AxisConfiguration in the running system. The correct way of defining a parameter is shown below: <parameter name="name of the parameter" >parameter value

Transport Receiver Depending on the underlying transport on which Axis2 is going to run, you need to have different transport receivers. The way you add them to the system is as follows: <parameter name="port" >6060 The above elements show the way of defining transport receivers in axis2.xml. Here the name attribute of the 'transportReceiver' element is the name of the transport receiver. It can be HTTP, TCP, SMTP, CommonsHTTP etc,. When the system starts up or when you set the transport at the client side, you can use these transport names to load the appropriate transport. Class attribute is to specify actual java classes that implement required interfaces for the transport. Any transport can have zero or more parameters, and if there are any, those

83

parameters can be accessed via the corresponding transport receiver.

Transport Sender Just as the transport receivers, you can register transport senders in the system, and later at run time, the senders can be used to send the messages. For example, consider Axis2 running under Apache Tomcat. Then Axis2 can use TCP transport senders to send messages rather than HTTP. The method of specifying transport senders is as follows: <parameter name="PROTOCOL" locked="xsd:false">HTTP/1.0 name: Name of the transport (you can have HTTP and HHTP1 as the transport name) class: Implementation class of the corresponding transport. Just as the transport receivers, transport senders can have zero or more parameters, and if there are any, then it can be accessed via the corresponding transport sender.

Phase Order Specifying the order of phases in the execution chain has to be done using the phase order element. It will look as follows: . The most interesting thing is that you can add handlers here as well. If you want to add a handler that should go into that phase, you can directly do that by adding a handler element into it. In addition to that, there is no hard coding work for the handler chain anywhere in Axis2 (at any Axis*). So all those configurations are also done in the phase order element. The complete configurations will look as follows:

84

name="Transport"> phase module author or service author can add any phase he wants --> name="OperationInPhase"/> name="PreDispatch"/> class="org.apache.axis2.engine.DispatchPhase"> class="org.apache.axis2.engine.AddressingBasedDispatcher"> name="PolicyDetermination"/>

85

type: the attribute represents the type of the flow. It can only be one of the following: •

InFlow



OutFlow



InFaultFlow



OutFaultFlow

In addition to that, the only child element that is allowed inside "phaseOrder" is the "phase" element which represents the available phases in the execution chain. The method of specifying phases inside "phaseOrder" is as follows: name: Name of the phase. There are a number of things that one has to keep in mind when changing a phaseOrder: For the phaseOrder types "InFlow" and "InFaultFlow" All the phases that are above the "Dispatch" phase, including the "Dispatch" phase, are known as "Global phases" . You can add any number of new phases here and they will be considered global. •

In these two phaseOrder types, the phases added after the "Dispatch" phase are known as "Operation phases". •

For the phaseOrder types "OutFlow" and "OutFaultFlow" All the phases that are below the "MessageOut" phase, including the "MessageOut" phase, are known as "Global phases". You can add new phases according to your requirement. •



The phases added before the "MessageOut" phase are known as "Operation phases".

Note : If you look closely at the default axis2.xml, you will be able to clearly identify it.

Module References If you want to engage a module, system wide, you can do it by adding a top level module element in axis2.xml. It should look as follows: <module ref="addressing"/> ref: the module name which is going to be engaged, system wide.

Listeners (Observers) In Axis2, AxisConfiguration is observable so that you can register observers into that. They will be automatically informed whenever a change occurs in AxisConfiguration. In the current implementation, the observers are informed of the following events: •

Deploying a Service



Removing a service



Activate/Inactivate Service



Module deploy



Module remove

Registering Observers is very useful for additional features such as RSS feed generation, which will provide service information to subscribers. The correct way of registering observers should as follows:

86

<listener class="org.apache.axis2.ObserverIMPL"> <parameter name="RSS_URL" >http://127.0.0.1/rss class: Represents an Implementation class of observer, and it should be noted that the Implementation class should implement AxisObserver interface, and the class has to be available in the classpath.

Service Configuration •

Writing services.xml

The description of services are specified using services.xml. Each service archive file needs to have a services.xml in order to be a valid service and it should be available in the META-INF directory of the archive file. A very simple services.xml is shown below: <service name="name of the service" scope="name of the scope" class="full qualifide name the service lifecycle class" targetNamespace="target namespase for the service"> <description> The description of the service HTTP <schema schemaNamespace="schema namespace"/> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass" locked="xsd:false">org.apache.axis2.sample.echo.EchoImpl Mapping to action <module ref=" a module name "/> <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>

name: The service name will be the name of the archive file if the .aar file contains only one service, or else the name of the service will be the name given by the name attribute. scope: (Optional Attribute) The time period during which runtime information of the deployed services will be available. Scope is of several types- "Application", "SOAPSession", "TransportSession", "Request". The default value (if you don't enter any value) will be "Request" class: (Optional attribute) The full qualified name of the service lifecycle implementation class. ServiceLifeCycle class is usefull when you want to do some tasks when the system starts and when it shutdowns. targetNamespace: (Optional Attribute) Target name space of the service. This value will be used when generating the WSDL. If you do not specify this value, the value will be calculated from the package name of the service impl class.

87

description: (Optional) If you want to display any description about the service via Axis2 web-admin module, then the description can be specified here. transports : (Optional) The transports to which the service is going to be exposed. If the transport element is not present, then the service will be exposed in all the transports available in the system. The transport child element specifies the transport prefix (the name of the transport specified in axis2.xml). parameters: A services.xml can have any number of top level parameters and all the specified parameters will be transformed into service properties in the corresponding AxisService. There is a compulsory parameter in services.xml called ServiceClass that specifies the Java class, which performs the above transformation. This class is loaded by the MessageReceiver. operations : If the service impl class is Java, then all the public methods in that service will be exposed. If the user wants to override it, he has to add the "operation" tag and override it. In a non-Java scenario or if you do not have a service class, then all the operations the user wants to expose by the service has to be indicated in the services.xml. It is specified as follows: <module ref=" a module name "/> <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> The only compulsory attribute here is "name", which represents the operation name that is going to be exposed. Any operation can contain module references as well as any number of parameters. The most interesting thing is that you can register custom message receivers per operation. Then the registered message receiver will be the message receiver for the corresponding operation. If you do not specify the message receiver, then the default message receiver will perform the operation.

Module Configuration •

Writing module.xml

The description of the module is specified using the module.xml. Each module archive file needs to have a module.xml in order to be a valid module, and it should be available in the META-INF directory of the archive file. A very simple module.xml is shown below:

88

<module class="org.apache.module.Module1Impl"> . . . . . . . . <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> <parameter name="para1" locked="xsd:true">10 class: (Optional attribute) Indicates the module implementation class. A module may or may not contain a module implementation class since the module can also be a collection of handlers. If a module contains an implementation class that implements the org.apache.axis2.modules.Module interface at deployment, its init(); method will be called. parameter: A module can contain any number of parameters and all the listed parameters in the module.xml will be transformed into the corresponding AxisModule of the module. flow: Defining of handlers in a module has to be done inside flows. There are four types of flows as listed below. You can add any number of handlers into a flow, and those handlers will be available in the corresponding chains at runtime, when they are engaged. •

InFlow



OutFlow



InFaultFlow



OutFaultFlow

operations: If a module wants to add an operation when it is engaged into a service, it can be done by adding an operation tag in module.xml. The method of specifying the operation is the same as operation in services.xml. handler: The Handler element consists of compulsory and optional attributes. The method of defining a handler will look as follows:

Compulsory Attributes: name: Name of the handler.

89

class: Handler implementation class. phase: Name of the phase that the handler should remain, in the execution chain. Optional Attributes : phaseLast: Indicates that the handler is the last handler of the phase. phaseFirst: Indicate that the handler is the first handler of the phase. before : Indicates that the current handler should be invoked before the handler specified by the before handler. after: Indicates that the current handler should be invoked after the handler specified by the after handler.

Apache Axis2 Web Administrator's Guide This document gives you detailed information on the administration console of the Apache Axis2 Web application. Apache Axis2 Administration is all about configuring Apache Axis2 at run time, where the configuration is transient. Send your feedback to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix every email subject with [Axis2].

Contents •

Introduction •



Login into Administration Site

Administration Options •

Tools •





Upload Service

System components •

Available services



Available service groups



Available modules



Globally engaged modules



Available phases

Execution chains •

Global chains



Operation specific chains



Engage module



Services





Deactivate Service



Activate Service



Edit service parameters

Contexts •

View Hierarchy

90

Introduction The Apache Axis2 Web application has three main sections: 'Services' lists all the available services deployed in this server, 'Validate' checks the system to see whether all the required libraries are in place and views the system information, and 'Administration' is the Axis2 Web Administration module which is the console for administering the Apache Axis2 installation. The Axis2 Web Administration module provides a way to configure Axis2 dynamically. It's important to note that this dynamic configuration will NOT be persistent, i.e., if the servlet container is restarted, then all the dynamic configuration changes will be lost.

Log on to the Administration Site Once Apache Axis2 is successfully installed, the Web application can be accessed (see Installation Guide for instructions). From the Axis2 Web Application Home page you can go to the Administration page by clicking the 'Administration' link. The Login page shown below will appear requesting the user name and password. The default user name is 'admin' (without quotes) and default password is 'axis2' (without quotes).

You can change the user name and password values by changing the following two parameters in the axis2.xml as required. <parameter name=”userName” locked=”false”>admin <parameter name=”password” locked=”false”>axis2 If the log on is successful, you will see the screen below. This is where you can view the configuration and the status of the running system and dynamically configure it.

91

Administration Options Tools •

Upload Service

System components •

Available services



Available service groups



Available modules



Globally engaged modules



Available phases

Execution chains •

Global chains



Operation specific chains

Engage module •

For all Services



For a Service Group



For a Service



For an Operation

Services

92



Deactivate service



Activate service



Edit service parameters

Contexts •

View Hierarchy

Apache Axis2 Web Application Home Page

Tools Upload Services You can upload packaged Apache Axis2 service archive files using this page. This can be done in two simple steps: •

Browse to the location and select the axisService archive file you wish to upload



Then click Upload

93

System components Available Services The functionality of the 'Available Services' option is almost the same as the functionality of the 'Services' option on the Axis2 Web Application Home page, where it displays a list of deployed services and their operations. As an additional feature, the 'Available Services' page lists details of modules that are engaged to the deployed services and their operations on a global, service or on an operation level. Using the 'Disengage' link, you can disengage the corresponding module as long as the module is not globally engaged (i.e., engaged to all the services and operations). Click on a specific service and it will give you the WSDL file of that particular service. Faulty services of this system will also be listed on this page. Click on a faulty service to view a page that lists the exception stack trace of the exception, which caused the service to be faulty.

94

Available Service Groups Service group is a logical collection of related services, and the 'Available Service Groups' link will list all the available service groups in the system.

95

Available Modules To view the available modules in the 'modules' directory of the repository, click 'Available Modules'. This will show you all the available modules in the system. Those modules can be engaged dynamically.

Globally Engaged Modules Click the 'Globally Engaged Modules' to view the globally engaged modules, if any. If a module is engaged globally, then the handlers that belong to that module will be executed irrespective of the service.

Available Phases The 'Available Phases' link will display all the available phases. In Axis2, there are two levels of phases: •

System predefined phases (not allowed to be changed)



User defined phases

The main difference between these two levels is that system predefined phases will be invoked irrespective of the services, while the user defined phases will be invoked when the dispatcher finds the operation. Note that it is essential for module developers and service writers to have a good understanding of phases and phase ordering.

96

Executions Chains Global Chains The 'Global Chains' link will display all the Global Execution Chains. The most interesting feature of the Axis2 Web Administration Module is that it provides a very basic method of viewing the global phase list and handlers inside the phases depending on both the phase and handler orders. This kind of information is extremely useful in debugging the system, as there is no other way to list out handlers in the global chains. If you engage a new module, the new handlers will be added to the global chains and will be displayed on this page.

97

Operation Specific Chains The 'Operation Specific Chains' link can be used to view the handlers corresponding to a given service in the same order as it is in the real execution chain.

98

Select the service of whose service handlers you wish to view from the list, and click 'View' to view the handlers. The page below shows the service handlers of the service version

99

Engaging Modules The 'Engaging Modules' link allows you to engage modules either globally (to all services), to a service group, to a service, or to an operation depending on the module implementation. If the module was designed to engage the handlers globally, then the handlers in the module can be included in any phase in the system. It can be either a system predefined phase or a user defined phase. On the other hand, if the module was implemented in such a way that it is going to be deployed to a service or to an operation, then the module cannot be included in any of the System Predefined Phases. Thus it can only be included in User Defined Phases. Immediately after engaging the module, you can see the status of the engagement indicating whether it is engaged properly or not.

Services Deactivate Service The 'Deactivate Service' link under the 'Services' list will lead to the page below. The Deactivate service functionality provides a way to remove unnecessary services from the running system, but the removal is transient--which means that if you restart the system, the service will be active. To deactivate a service, select a service from the list, select the 'Deactivate service' check box, and then click 'Deactivate'.. The 'Clear' button will clear the 'Deactivate service' check box.

100

Activate Service The 'Activate Service' link under the 'Services' list will lead to the page below. The Activate service functionality provides a way to activate services while the system is running, but the activation is transient-- which means that if you restart the system, the service will be inactive. To activate a service, select a service from the list, select the 'Activate Service' check box, then click 'Activate'. The 'Clear' button will clear the 'Activate service' check box.

101

Edit Service Parameters This functionality provides a way to change the parameters in a service or its operations. These changes will be transient too, which means if you restart the system, the changes will not be reflected. The 'Edit Parameters' link under the 'Services' list (on the navigation bar) will link to the page where you can select the services of which you want to edit the parameters. Once the service is selected, click 'Edit Parameters'.. This will open the page shown below.

102

Contexts View Hierarchy By listing the current context hierarchy, the 'View Hierarchy' link provides a means to look at the system state at run time. This will list out all the available service group contexts, service contexts, operation contexts, etc.

Apache Axis2 Architecture Guide This document gives an introduction to Axis2's modular architecture with explanations on every module. Send your feedback to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

Contents •

The Big Picture



Requirement of Axis2



Axis2 Architecture •

Core Modules



Other Modules

103



Information Model



XML Processing Model



SOAP Processing Model







Axis2 Default Processing Model



Processing an Incoming SOAP Message



Processing of the Outgoing Message



Extending the SOAP Processing Model •

Extending the SOAP Processing Model with Handlers



Extending the SOAP Processing Model with Modules

Deployment •

The axis2.xml file



Service Archive



Module Archive

Client API •

One Way Messaging Support



Request Response Messaging Support



Transports



Code Generation



Data Binding •

Integration with Code Generation Engine



Serialization and De-Serialization

The Big Picture A new architecture for Axis was introduced during the August 2004 Summit in Colombo, Sri Lanka. This new architecture on which Axis2 is based is more flexible, efficient, and configurable in comparison to Axis1.x architecture. Some well established concepts from Axis 1.x, like handlers etc., have been preserved in this new architecture. Any architecture is a result of what that architecture should yield. The success of an architecture should be evaluated based on the requirements expected to be met by that architecture. Let us start our journey into Axis2 by looking at the requirements.

Requirement of Axis2 In SOAP terminology, a participant who is taking part in a Web service interaction is known as a SOAP Node. Delivery of a single SOAP Message is defined based on two participants, SOAP Sender and SOAP Receiver. Each SOAP message is sent by a SOAP Sender and received by a SOAP Receiver. A single SOAP delivery is the most basic unit that builds the Web service interaction. Each SOAP Node may be written in specific programming language, may it be Java, C++, .NET or Perl, but the Web services allow them to interoperate. This is possible because on the wire each Web service interaction is done via SOAP, which is common to every SOAP Node.

104

Web service middleware handles the complexity in SOAP messaging and lets the users work with the programming language they are accustomed to. Axis2 allows Java users to invoke Web services using Java representations, and handles the SOAP messaging behind the curtain. Axis2 handles SOAP processing along with numerous other tasks. This makes life of a Web service developer a whole lot easier. Following are the identified requirements: 1. Provide a framework to process the SOAP messages. The framework should be extensible and the users should be able to extend the SOAP processing per service or per operation basis. Furthermore, it should be able to model different Message Exchange Patterns (MEPs) using the processing framework. 2. Ability to deploy a Web service (with or without WSDL) 3. Provide a Client API that can be used to invoke Web services. This API should support both the Synchronous and Asynchronous programming models. 4. Ability to configure Axis2 and its components through deployment. 5. Ability to send and receive SOAP messages with different transports. Apart from the above functionalities, performance in terms of memory and speed is a major consideration for Axis2. Axis2 Core Architecture is built on three specifications- WSDL, SOAP and WS-Addressing. Other specifications like JAX-RPC, SAAJ and WS-Policy are layered on top of the Core Architecture.

Axis2 Architecture Axis2 architecture lays out some principals to preserve the uniformity. They are as follows: Axis2 architecture separates the logic and the states. Code that does the processing does not have a state inside Axis2. This allows code to be executed freely by parallel threads. •

All the information is kept in one information model, allowing the system to be suspended and resumed. •

Axis2 architecture is modular. Therefore, Axis2 Framework is built up of core modules that collectively make up the core architecture of Axis2. Non-core/other modules are layered on top of this core modules/architecture.

105

Core Modules: Information Model - Axis2 defines a model to handle information and all states are kept in this model. The model consists of a hierarchy of information. The system manages the life cycle of the objects in this hierarchy. •

XML processing Model - Handling the SOAP Message is the most important and most complex task. The efficiency of this is the single most important factor that decides the performance. It makes sense to delegate this task to a separate sub-project under the Web services project, allowing that sub-project (AXIOM or AXis Object Model) to provide a simple API for SOAP and XML info-set. It will hide the complexities of the efficient XML processing within the implementation. •

SOAP Processing Model - This controls the execution of the processing. The model defines different phases the execution would walk through, and the user can extend the Processing Model at specific places. •

Deployment Model - The Axis2 deployment model allows the user to deploy services, configure the transports, and extend the SOAP Processing model per system, service, or operation basis. •

Client API - This provides a convenient API for users to communicate with Web services using Axis2. There are a set of classes to interact with IN-OUT and IN-Only style Message Exchange Patterns (MEPs), where they can be used to construct any other MEP. (Please note that even if the client API has in-built support for the above named MEPs, it does not by any means limit Axis2's flexibility to support custom MEPs.) •

Transports - Axis2 defines a transport framework that enables the user to use multiple different transports. The transports fit into specific places in the SOAP processing model. The implementation provides a few common transports and the user can write or plug-in new ones if and when it is needed. •

Other Modules: Code Generation - Axis2 provides a code generation tool that generates server side and client side code along with descriptors and a test case. The generated code would simplify the service deployment and the service invocation. This would increase the usability of Axis2. •

Data Binding - The basic client API of Axis2 lets the users process SOAP at the infoset level, where as data binding extends it to make it more convenient to the users by encapsulating the infoset layer and providing a programming language specific interface. •

106

Information Model Information Model has two main hierarchies-Contexts and Descriptions. This model is described in UML notations below.

( A ----<> B says, B has 1 or more objects of A. A------>B says, the given relationship holds between A and B.) The two hierarchies are connected as shown in the above figure. The Description hierarchy represents the static data. This data may be loaded from a configuration file that exists throughout the lifetime of Axis2. For example, deployed Web services, operations, etc. On the other hand, the context hierarchy holds more dynamic information about the things that have more than one instance (e.g.Message Context). These two hierarchies create a model that provides the ability to search for key value pairs. When the values are searched at a given level, they are searched while moving up the hierarchy until a match is found. In the resulting model, the lower levels override the values in the upper levels. For example, when a value is looked up in the Message Context and is not found, it would be looked up in the Operation Context, etc, up the hierarchy. The Search is first done up the hierarchy, and if the starting point is a Context then it searches in the Description

107

hierarchy as well. This allows the user to declare and override values, with the result being a very flexible configuration model. The flexibility could be the Achilles heel for the system as the search is expensive, specially for something that does not exist. Yet in the final analysis, developers believe that the flexibility would serve better in this instant. Context Configuration Context

Description Holds the Axis2's run time status. A deep copy of this would essentially make a copy of Axis2.

Configuration Axis Configuration

Description Holds all global configurations. Transports, global modules, parameters, and services etc.

Holds information about a particular usage of the respective service group. The life of a Service Group Context starts when a user Holds deployment time Service Group starts interacting with a AxisServiceGroup information about a particular Context service that belong to this service group. service group. This can be used to share information between services (within the same service group) in a single interaction.

Service Context

This context is available throughout the usage of the respective service. This can be used to share information between several MEPs of the AxisService same service, within a single interaction. The life cycle depends on the scope of the service.

Holds the Operations and the service level configurations

Operation Context

Holds the information about the current MEP instance, AxisOperation maintain the messages in the current MEP etc.

Holds the operation level configurations

Message Context

Holds all the information about the Message currently being executed.

Holds message level static information like the schema of the particular message.

AxisMessage

XML Processing Model As we mentioned above, the XML processing model of Axis2 has become a separate subproject, called Apache Axiom, in the Apache Web services project. Please refer to the OM Tutorial for more information.

108

SOAP Processing Model

The architecture identified two basic actions a SOAP processor should perform, sending and receiving SOAP messages. The architecture provides two Pipes ('Flows'), to perform these two basic actions. The Axis Engine or the driver of Axis2 defines two methods send() and receive() to implement these two Pipes. The two pipes are named In Pipe and Out Pipe, and the complex Message Exchange Patterns (MEPs) are constructed by combining these two pipes. Extensibility of the SOAP processing model is provided through handlers. When a SOAP message is being processed, the handlers that are registered will be executed. The handlers can be registered in global, service, or operation scopes and the final handler chain is calculated combining the handlers from all the scopes. The handlers act as interceptors and they process parts of the SOAP message and provide add-on services. Usually handlers work on the SOAP headers, yet they may access or change the SOAP body as well. When a SOAP message is being sent through the Client API, an Out Pipe would begin, the Out Pipe invokes the handlers and end with a Transport Sender that sends the SOAP message to the target endpoint. The SOAP message is received by a Transport Receiver at the target endpoint, which reads the SOAP message and starts the In Pipe. The In Pipe consists of handlers and ends with the Message Receiver, which consumes the SOAP message. The processing explained above happens for each and every SOAP message that is exchanged. After processing one message, Axis2 may decide to create other SOAP messages, in which case more complex message patterns emerge. However, Axis2 always views the SOAP message in terms of processing a single message. The combination of the messages are layered on top of that basic framework. The two pipes does not differentiate between the Server and the Client. The SOAP Processing Model handles the complexity and provides two abstract pipes to the user. The different areas or the stages of the pipes are given names, and according to Axis2 slang, they are named 'phases'. A Handler always runs inside a phase, and the phase provides a mechanism to specify the ordering of handlers. Both Pipes have built-in phases, and both define the areas for 'User Phases' which can be defined by the user.

Axis2 Default Processing Model Axis2 has some inbuilt handlers that run in inbuilt phases and they create the default configuration for Axis2. We will be looking more in to how to extend the default processing Model in the next section.

109

There are three special handlers defined in Axis2. 1. Dispatchers - Finds the service and the operation the SOAP message is directed to. Dispatchers always run on the In-Pipe and inside the Dispatch phase. The in-built dispatchers dispatch to a particular operation depending on various conditions like WSAddressing information, URI information, SOAP action information, etc. ( See more information on Dispatching) Message Receiver - Consumes the SOAP message and hands it over to the application. The message receiver is the last handler of the in-pipe •

Transport Sender - Sends the SOAP message to the SOAP endpoint the message is destined to. Always runs as the last handler in the out-pipe •

Processing an Incoming SOAP Message An incoming SOAP message is always received by a Transport Receiver waiting for the SOAP messages. Once the SOAP message arrives, the transport Headers are parsed and a Message Context is created from the incoming SOAP message. This message context encapsulates all the information, including the SOAP message itself, transport headers, etc., inside it. Then the In Pipe is executed with the Message Context. Let us see what happens at each phase of the execution. This process can happen in the server or in the client. 1. Transport Phase - The handlers are in the phase that processes transport specific information such as validating incoming messages by looking at various transport headers, adding data into message context, etc. 2. Pre-Dispatch Phase- The main functionality of the handlers in this phase is to populate message context to do the dispatching. For example, processing of addressing headers of the SOAP message, if any, happens in this phase. Addressing handlers extract information and put them in to the message context. 3. Dispatch Phase - The Dispatchers run in this phase and try to find the correct service and operation this particular message is destined for. The post condition of the dispatch phase (any phase can contain a post condition) checks whether a service and an operation were found by the dispatchers. If not, the execution will halt and give a "service not found' error. 4. User Defined Phases - Users can engage their custom handlers here. 5. Message Validation Phase - Once the user level execution has taken place, this phase validates whether SOAP Message Processing has taken place correctly. 6. Message Processing Phase - The Business logic of the SOAP message is executed here. A Message Receiver is registered with each Operation. This message receiver (associated to the particular operation) will be executed as the last handler of this phase. There may be other handlers in any of these phases. Users may use custom handlers to override the mechanics in each of these phases.

Processing of the Outgoing Message TheOut Pipe is simpler because the service and the operation to dispatch are known by the time the pipe is executed. The Out Pipe may be initiated by the Message Receiver or the Client API implementation. Phases of the Out Pipe are described below: 1. Message Initialize Phase - First phase of the Out Pipe. Serves as the placeholder for the custom handlers.

110

2. User Phases - Executes handlers in user-defined phases. 3. Transports Phase - Executes any transport handlers taken from the associated transport configuration. The last handler would be a transport sender which will send the SOAP message to the target endpoint.

Extending the SOAP Processing Model Above, we discussed the default processing model of Axis2. Now let us discuss the extension mechanism for the SOAP processing model. After all, the whole effort of making this SOAP engine/processing model was focused on making it extendable. The idea behind introducing step-wise processing of the SOAP message in terms of handlers and phases is to allow easier modification of the processing order. The notion of phases makes it easier to place handlers in between other handlers. This enables modification of the default processing behavior. The SOAP Processing Model can be extended with handlers or modules.

Extending the SOAP Processing Model with Handlers The handlers in a module can specify the phase they need to be placed in. Furthermore, they can specify their location inside a phase by providing phase rules. Phase rules will place a handler, 1. as the first handler in a phase, 2. as the last handler in a phase, 3. before a given handler, 4. or after a given handler.

Extending the SOAP Processing Model with Modules Axis2 defines an entity called a 'module' that can introduce handlers and Web service operations. A Module in terms of Axis2 usually acts as a convenient packaging that includes: •

A set of handlers and



An associated descriptor which includes the phase rules

Modules have the concept of being 'available' and 'engaged'. 'Availability' means the module is present in the system, but has not been activated, i.e., the handlers included inside the module have not been used in the processing mechanism. When a module is 'engaged' it becomes active and the handlers get placed in the proper phases. The handlers will act in the same way as explained in the previous section. Usually a module will be used to implement a WS-* functionality such as WS-Addressing. Apart from the extension mechanism based on the handlers, the WS-* specifications may suggest a requirement for adding new operations. For example, once a user adds Reliable Messaging capability to a service, the "Create Sequence" operation needs to be available to the service endpoint. This can be implemented by letting the modules define the operations. Once the module is engaged to a service, the necessary operations will be added to that service. A service, operation, or the system may engage a module. Once the module is engaged, the handlers and the operations defined in the module are added to the entity that engaged them. Modules cannot be added (no hot deployment) while the Axis2 engine is running, but they will be available once the system is restarted.

Deployment The Deployment Model provides a concrete mechanism to configure Axis2. This model has

111

three entities that provide the configuration.

The axis2.xml file This file holds the global configuration for the client and server, and provides the following information: 1. The global parameters 2. Registered transport-in and transport-outs 3. User-defined phase names 4. Modules that are engaged globally (to all services) 5. Globally defined Message Receivers

Service Archive The Service archive must have a META-INF/services.xml file and may contain the dependent classes. The services.xml file has the following information. 1. Service level parameters 2. Modules that are engaged at service level 3. Service Specific Message Receivers 4. Operations inside the service

Module Archive Module archive must have a META-INF/module.xml file and dependent classes. The module.xml file has Module parameters and the Operations defined in the module. When the system starts up, Axis2 prompts the deployment model to create an Axis Configuration. The deployment model first finds the axis2.xml file and builds the global configuration. Then it checks for the module archives and then for the service archives. After that, the corresponding services and modules are added to the Axis Configuration. The system will build contexts on top of the Axis Configuration. After this, Axis2 is ready to send or receive SOAP messages. Hot deployment is only allowed for services.

Client API There are three parameters that decide the nature of the Web service interaction. 1. Message Exchange Pattern (MEP) 2. The behavior of the transport, whether it's One-Way or Two-Way 3. Synchronous/ Asynchronous behavior of the Client API Variations of the three parameters can result in an indefinite number of scenarios. Even though Axis2 is built on a core that supports any messaging interaction, the developers were compelled to provide in-built support for only two most widely used Message Exchange Patterns (MEPs). The two supported MEPs are One-Way and the In-Out (Request-Response) scenarios in the Client API. The implementation is based on a class called ServiceClient and there are extensions for each MEP that Axis2 Client API supports.

112

One Way Messaging Support The One-Way support is provided by the fireAndForget method of ServiceClient. For one way invocations, one can use HTTP , SMTP and TCP transports. In the case of the HTTP transport, the return channel is not used, and the HTTP 202 OK is returned in the return channel.

In-Out (Request Response) Messaging Support The In-Out support is provided by the sendReceive() method in ServiceClient. This provides a simpler interface for the user. The Client API has four ways to configure a given message exchange 1. Blocking or Non-Blocking nature - this can be decided by using sendReceive() or sendReceiveNonBlocking() methods 2. Sender transport - transport that sends the SOAP message 3. Listener transport - transport that receives the response 4. Use Separate Channel - determines whether the response is sent over a separate transport connection or not. This can be false only when the sender and listener transport is same and is a Two-Way transport. Depending on the values of the above four parameters, Axis2 behaves differently.

Transports Axis2 has two basic constructs for transports, namely: Transport Senders and Transport Receivers. These are accessed via the AxisConfiguration. The incoming transport is the transport via which the AxisEngine receives the message. The outgoing transport is decided based on the addressing information (wsa:ReplyTo and wsa:FaultTo). If addressing information is not available and if the server is trying to respond, then the out going transport will be the outputstream of the incoming transport (if it is twoway transport). At the client side, the user is free to specify the transport to be used. Transport Senders and Transport Receivers contain the following information. 1. Transport Sender for Out Configuration 2. Transport Listener for In Configuration 3. Parameters of the transport Each and every transport out configuration defines a transport sender. The transport sender sends the SOAP message depending on its configuration. The transport receiver waits for the SOAP messages, and for each SOAP message that arrives, it uses the In Pipe to process the SOAP message. Axis2 presently supports the following transports: 1. HTTP - In HTTP transport, the transport listener is a servlet or org.apache.axis2.transport.http.SimpleHTTPServer provided by Axis2. The transport sender uses commons-httpclient to connect and send the SOAP message. 2. TCP - This is the simplest transport, but needs the WS - Addressing support to be functional. 3. SMTP - This works off a single email account. Transport receiver is a thread that checks for emails in fixed time intervals.

113

4. JMS

Code Generation Although the basic objective of the code generation tools has not changed, the code generation module of Axis2 has taken a different approach to generate code. Primarily, the change is in the use of templates, namely XSL templates, which gives the code generator the flexibility to generate code in multiple languages. The basic approach is to set the code generator to generate an XML, and parse it with a template to generate the code file. The following figure describes how this shows up in the architecture of the tool.

The fact here is that it is the same information that is extracted from the WSDL no matter what code is generated. First, an AxisService is populated from a WSDL. Then the code generator extracts information from the AxisService and creates an XML, which is language independent. This emitted XML is then parsed with the relevant XSL to generate code for the relevant language. No matter what the output language is, the process is the same except for the template that is being used.

114

Data Binding Integration with the Code Generation Engine Databinding for Axis2 is implemented in an interesting manner. Databinding has not been included in the core deliberately, and hence the code generation allows different data binding frameworks to be plugged in. This is done through an extension mechanism where the codegen engine first calls the extensions and then executes the core emitter. The extensions populate a map of QNames vs. class names that is passed to the code generator on which the emitter operates on. The following diagram shows the structure:

The following databinding extensions are available: 1. ADB - ADB (Axis Data Binding ) is a simple framework that allows simple schemas to be compiled. It is lightweight and simple, works off StAX and fairly performant. However, it does not support the complete set of schema constructs and is likely to complain for certain schemas! 2. XMLBeans - XMLbeans claims that it supports the complete schema specification, and it is preferred if full schema support is needed! 3. JAX-Me - JaxMe support has been added in a similar manner to XMLbeans and

115

serves as another option for the user 4. JibX - This is the most recent addition to the family of databinding extensions, and it is also another option the users have for data binding.

Serialization and De-Serialization of Data bound classes AXIOM is based on a StAX API (Streaming API for XML). Xml-beans supports StAX API. Data binding in Axis2 is achieved through interfacing the AXIOM with the Xml-beans using the StAX API, which is supported by both parties. At the time of code generation, there will be utility methods generated inside the stub (or the message receiver) that can de-serialize from AXIOM to data bound object and serialize from data bound object to AXIOM. For example, if the WSDL has an operation called "echoString", once the code is generated, the following methods will be generated inside the relevant classes.

public static org.apache.axiom.om.OMElement toOM(org.soapinterop.xsd.EchoStringParamDocument param)// This method will handle the serialization. public static org.apache.xmlbeans.XmlObject fromOM(org.apache.axis2.om.OMElement param, java.lang.Class type) //This method will handle the de-serialization.

POJO Web Services using Apache Axis2 Want a quick way to get a Web service up and running in no time? Then you should consider creating a Plain Old Java Object (POJO) that you can deploy using Apache Axis2 on Apache Tomcat. POJOs are fast to build and easy to maintain, which means you'll save a lot of time building and debugging your code. This document shows you how to take a simple POJO, and deploy it on Apache Tomcat as a Web service in the exploded directory format. You'll also learn how to take a POJO based on the Spring Framework, and deploy that as an AAR packaged Web service on Tomcat.

Content •

Introduction



The POJO



POJO Web service using Apache Axis2 and Tomcat •

Defining the Service: services.xml



Building the POJO Web Service Using Ant



Testing the POJO Web Service Using RPCServiceClient •





Limitations and Strengths of POJO

Spring-based POJO Web Service •

Quick Introduction



The Service Definition: services.xml



Initializing the Spring application context: SpringInit



Testing Using an RPCServiceClient

Summary

116



For Further Study

Introduction The task of building a Web service can sometimes be overwhelming, but not with POJOs! The old-school Plain Old Java Object is a simple and quick way to get most, if not all, of your currently existing Java classes up on the Web as readily accessible Web services. This document describes how to build a POJO-style Web service with Apache Axis2 and Tomcat. It is organized as follows: •

The POJO: This is the Java class that you'll use throughout this document



POJO deployment



Test the POJO Web service using an RPC based client



Limitations of straight POJO



Spring-based POJO Web service and deployment

The code for the document can be found at Axis2_HOME/samples/pojoguide and Axis2_HOME/samples/pojoguidespring once you extract the Axis2 Standard Distribution. (It is better to get it now as it will help you to follow along.) Let's get started.

The POJO The POJO you'll be using throughout this document is a Weather service POJO that consists of two classes: WeatherService and Weather. Weather contains the Weather data: Temperature, forecast, rain (will it rain?), and howMuchRain (See Code Listing 1). Code Listing 1: The Weather POJO package sample.pojo.data; public class Weather{ float temperature; String forecast; boolean rain; float howMuchRain; public void setTemperature(float temp){ temperature = temp; } public float getTemperature(){ return temperature; } public void setForecast(String fore){ forecast = fore; } public String getForecast(){ return forecast; } public void setRain(boolean r){ rain = r; }

117

public boolean getRain(){ return rain; } public void setHowMuchRain(float howMuch){ howMuchRain = howMuch; } public float getHowMuchRain(){ return howMuchRain; } } And here's the WeatherService class, shown in Code Listing 2. Code Listing 2: The WeatherService class package sample.pojo.service; import sample.pojo.data.Weather; public class WeatherService{ Weather weather; public void setWeather(Weather weather){ this.weather = weather; }

}

public Weather getWeather(){ return this.weather; }

Note that it's all just straight POJOs with field items and getter and setter methods for each field. Next, you'll take a look at what you need to do to make it ready for deployment on Apache Axis2 and Tomcat.

POJO Web Service Using Apache Axis2 and Tomcat Got the POJOs? Great. This section will show you how to package them in the exploded directory format for easy deployment. First you'll look at the services.xml file that defines the Web service, and then you'll build the files using Apache Ant, and deploy the Web service on Tomcat.

Defining the Service: services.xml Before Axis2 can understand what is going on, you have to tell it to use the services.xml file. Let's get right into it (see Code Listing 3). Code Listing 3: The service definition file: services.xml

118

<service name="WeatherService" scope="application"> <description> Weather POJO Service <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass"> sample.pojo.service.WeatherService The name of the service is specified as WeatherService and the scope of the service is application. As you can see in the WeatherService POJO, there are two methods: IN-ONLY method and IN-OUT method. Hence the messageReceiver elements are ordered within the messageReceivers tag. Lastly, the ServiceClass parameter specifies the class of the Web service, which is sample.pojo.service.WeatherService. When operations of your Web service get called, the methods of the WeatherService class will be called. Next let usl take a look at an easy method of building your application using Ant.

Building the POJO Web Service Using Apache Ant Ant is a slick build tool. It helps reduce the time to build the applications, and several of the Axis2 command-line tools create the build.xml files for you. (We will not be going into too much detail on the build.xml file that you'll be using.) Here are the main Ant tasks you'll be using: generate.service -- This Ant task builds the service relevant source, and copies the files to build/WeatherService •

rpc.client -- This task builds the client relevant files, builds a JAR at build/lib/rpcclient.jar, and then runs the client •

Before you can build the source, you'll need to download the Axis2 1.2-bin and 1.2-war distributions from here. Then modify the following line inside the build.xml file (in the Axis2_HOME/samples/pojoguide directory in the extracted Axis2 1.2 Standard Binary (bin) Distribution) : ●

<property name="axis2.home" value="c:\apps\axis2" />

This modification contains the path to the root of the unzipped Axis2 1.2-bin download. With that explanation, you'll now build the source by typing the following: ant The following directory format should now exist at build/WeatherService: - WeatherService - META-INF - services.xml - sample - pojo - data - Weather.class - service - WeatherService.class

119

Simple isn't it? An excellent way to dive into Web services development. Now get a Tomcat distribution (I used v5.5), and start it up by running bin/startup.bat or bin/startup.sh. Once it's running, deploy the Axis2 1.2-war by copying the axis2.war file to Tomcat's webapps directory. Tomcat will proceed by deploying axis2 and un-archiving it into the webapps directory. Now copy the WeatherService directory that was created at the time of building our project to: /webapps/axis2/WEB-INF/services. The service should deploy quickly. You willl test the Web service using the RPCServiceClient in the next section.

Testing the POJO Web Service Using RPCServiceClient OK, so the Web service should be running on Tomcat. Now you'll build a simple RPCServiceClient and test the POJO Web service. You'll first start out with the class constructs, creating the RPCServiceClient and initializing the values of the Weather class within the Web service (See Code Listing 4). Code Listing 4: Setting the weather package sample.pojo.rpcclient; import javax.xml.namespace.QName; import import import import

org.apache.axis2.AxisFault; org.apache.axis2.addressing.EndpointReference; org.apache.axis2.client.Options; org.apache.axis2.rpc.client.RPCServiceClient;

import sample.pojo.data.Weather; public class WeatherRPCClient { public static void main(String[] args1) throws AxisFault { RPCServiceClient serviceClient = new RPCServiceClient(); Options options = serviceClient.getOptions(); EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/WeatherService"); options.setTo(targetEPR); // Setting the weather QName opSetWeather = new QName("http://service.pojo.sample/xsd", "setWeather"); Weather w = new Weather(); w.setTemperature((float)39.3); w.setForecast("Cloudy with showers"); w.setRain(true); w.setHowMuchRain((float)4.5); Object[] opSetWeatherArgs = new Object[] { w }; ...

serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs);

120

The most interesting code to note is in bold font. Notice the targetEPR variable you create, setting the endpoint reference to http://localhost:8080/axis2/services/WeatherService. This is where you deployed it on Axis2. You can also verify this by asking Axis2 to list its services by going to the following URL: http://localhost:8080/axis2/services/listServices. Next the opSetWeather variable gets setup, pointing to the setWeather operation. Then the Weather data is created and initialized. Lastly, you invoke the Web service, which initializes the weather data (you'll verify this soon). Next you get back the weather data (see Code Listing 5). Code Listing 5: Getting the weather data ... serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs); // Getting the weather QName opGetWeather = new QName("http://service.pojo.sample/xsd", "getWeather"); Object[] opGetWeatherArgs = new Object[] { }; Class[] returnTypes = new Class[] { Weather.class }; Object[] response = serviceClient.invokeBlocking(opGetWeather, opGetWeatherArgs, returnTypes); Weather result = (Weather) response[0]; if (result == null) { System.out.println("Weather didn't initialize!"); return; } ...

First you set the operation in opGetWeather to getWeather. Then you create an empty argument list. Note that this time you expect something back from the Web service, and so you create a list of return types. Then you invoke the Web service using a blocking call and wait for the weather data to be returned to you, and you place it in the result variable. Lastly, you make sure it isn't null and that it was successfully initialized by the previous call to setWeather. Now display the data to verify it. (see Code Listing 6). Code Listing 6: Displaying the data ... }

return;

// Displaying the result System.out.println("Temperature result.getTemperature()); System.out.println("Forecast result.getForecast()); System.out.println("Rain result.getRain()); System.out.println("How much rain (in inches) result.getHowMuchRain()); } }

121

: " + : " + : " + : " +

You should receive the data shown in Code Listing 7. Code Listing 7: Output from running the client rpc.client.run: [java] Temperature [java] Forecast [java] Rain [java] How much rain (in inches)

: : : :

39.3 Cloudy with showers true 4.5

Excellent! You have a working POJO Web service! Next you'll quickly morph this one into a Spring based POJO.

Limitations and Strengths of POJO We've covered the strengths of using POJO based Web services, but what about any limitations? One main limitation of POJO based Web services is the lack of initialization support (meaning that you have to go into your Web service and initialize the values before the Web service is completely useful). However, you'll soon see how to overcome that limitation with a Spring based POJO, which is covered next.

Spring-based POJO Web Service Spring is a hot framework for J2EE and makes bean usage a breeze. You'll use it in this section to create a Spring based POJO Web service. For this section, you'll need the spring.jar from the latest 1.x Spring download.

Quick Introduction If you take a look at the source code of this document in Axis2_HOME/samples/pojoguidespring (to see how the Spring based POJO Web service is coded), you can see that the Weather class didn't change at all and the WeatherService class only got its name changed to WeatherSpringService. You'll also notice an applicationContext.xml file, which we'll cover later. It is used to setup the beans used in our Web service. Now you might wonder what the SpringInit.java class is for. This service is necessary to initialize the Spring Framework's application context. The client is pretty much the same, except you won't use it to initialize the Weather data in the Web service, since Spring does that for you using Inversion of Control (IoC), which is covered next.

The Service Definition: services.xml Since the core POJOs didn't change, you move straight to the services.xml file. It's a bit longer this time because it instantiates two services in one file (see Code Listing 7). Code Listing 7: Defining the services: services.xml <serviceGroup> <service name="SpringInit" class="sample.spring.service.SpringInit"> <description> This web service initializes Spring.

122

<parameter name="ServiceClass"> sample.spring.service.SpringInit <parameter name="ServiceTCCL">composite <parameter name="load-on-startup">true <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> <service name="WeatherSpringService"> <description> Weather Spring POJO Axis2 AAR deployment <parameter name="ServiceClass"> sample.spring.service.WeatherSpringService <parameter name="ServiceObjectSupplier"> org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObject Supplier <parameter name="SpringBeanName"> weatherSpringService <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>

You'll see a few familiar items in the above listing, and several changes. Once again, the items in bold are most important. The ServiceTCCL property under the SpringInit service makes sure that the Spring class loader is used for the Web service, allowing it to properly instantiate the Spring application context. The load-on-startup variable is a must-have so that the service loads up immediately on startup, creating the Spring application context. The WeatherSpringService stays similar to the WeatherService previously with a couple of additions: The ServiceObjectSupplier provides the service with the Spring application context, making it "Spring Aware." Lastly, the SpringBeanName points to the name of the bean associated with this Web service, which is defined in the applicationContext.xml file (essentially the WeatherSpringService). We'll cover the applicationContext.xml file next. The application context, applicationContext.xml file tells the Spring Framework what beans are defined. For this example, you'll define three of them (see Code Listing 8). Code Listing 8: Defining the application context: applicationContext.xml

123

<property name="weather" ref="weatherBean"/> <property name="temperature" value="89.9"/> <property name="forecast" value="Sunny"/> <property name="rain" value="false"/> <property name="howMuchRain" value="0.2"/>


The first one is Axis2's hook into Spring's application context (needed since AAR deployment is quite different from regular WAR deployment). Next, you define the bean to which the services.xml file points, which is the weatherSpringService bean that points to the WeatherSpringService class. It has one field property that gets initialized by the Spring Framework - weather. This will be set to the weatherBean. The weatherBean is an instantiation of the Weather class that holds information on the weather. Spring will initialize it to the values shown above, and set the Weather object in the WeatherSpringService class to the weatherBean instantiation. Thus, when you deploy the Web service, you won't have to instantiate the values because they'll already be set. Next up is the SpringInit class.

Initializing the Spring Application Context: SpringInit Without the Spring application context being initialized quickly, you'll run into problems. The SpringInit class initializes the Spring application context on startup because it is a ServiceLifeCycle class whose startUp method gets called upon loading the class (and because its load-on-startup property is set in the services.xml file). The only code worth mentioning in this class is shown in Code Listing 9. Code Listing 9: SpringInit's startUp method public void startUp(ConfigurationContext ignore, AxisService service) { ClassLoader classLoader = service.getClassLoader(); ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"}, false); appCtx.setClassLoader(classLoader); appCtx.refresh(); if (logger.isDebugEnabled()) { logger.debug("\n\nstartUp() set spring classloader " + "via axisService.getClassLoader() ... "); } }

Note that this method retrieves the Spring class loader, and creates an application context with applicationContext.xml as the parameters. This new application context then gets the Spring class loader as its class loader. The Spring Framework is now up and ready for our WeatherSpringService.

124

Build and Deploy Using Apache Axis2 and Tomcat Your POJO is now ready for primetime within the Spring Framework. Before you build, you'll first need to make sure the axis2-spring-1.2.jar and spring.jar files are in the project's Axis2_HOME/lib directory. Note: The service will not deploy if you add the above .jar files to the service archive due to class loding issues. Now build the source and create an AAR file by typing: ant It'll be created at target/WeatherSpringService.aar. Copy it home>/webapps/axis2/WEB-INF/services, and Axis2 should deploy it quickly.

to


Next, test the Web service to see whether Spring will really initialize the weather data for you.

Testing Using an RPCServiceClient It's as simple as it was for the other Web service, except this time type: ant rpc.client Feel free to browse the code for this client in src/client/WeatherSpringRPCClient.java. Essentially, this client does the same thing as the client testing the WeatherService. Except that this one skips the "Setting the weather" task since the weather data should have already been set by the Spring framework at startup. Thus, you should get the following as output from the client: run.client: [javac] Compiling 1 source file to C:\axis21.2\samples\pojoguidespring\build\cl asses [java] Temperature : 89.9 [java] Forecast : Sunny [java] Rain : false [java] How much rain (in inches) : 0.2 Which are exactly the values you set in the applicationContext.xml file!

Summary Apache Axis2 is an excellent way to expose your POJOs as Web services. Spring adds greater flexibility to your POJOs by adding beans support and initialization abilities, along with all the other goodies provided by the Spring framework.

For Further Study Apache Axis2: ●

http://ws.apache.org/axis2/

Axis2 Architecture: ●

http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html

Introduction to Apache Axis2: ●

http://www.redhat.com/magazine/021jul06/features/apache_axis2/

Working With Apache Axis2: ●

http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2

125

Apache Tomcat: ●

http://tomcat.apache.org

Spring Framework: ●

http://www.springframework.org/

Axis2 Integration with the Spring Framework This document is a guide on how to use Axis2 with the Spring Framework

Content •

Introduction



Configuring Axis2 to be Spring Aware •

Programming Model



Simple Spring Config Example



With a ServletContext



Without a ServletContext



Putting it All Together



Spring Inside an AAR •

The Spring Inside an AAR Layout



The Spring Inside an AAR init Class



Known Issues Running Spring Inside the AAR

Introduction Axis2 and Spring integration takes place when Spring supplies one of its pre-loaded beans to the Axis2 Message Receiver defined in the AAR services.xml. Axis2 typically uses reflection to instantiate the ServiceClass defined in the services.xml used by the Message Receiver. Alternatively, you can define a ServiceObjectSupplier that will supply the Object. This guide describes how to use two separate ServiceObjectSupplier classes that are a part of the Axis2 standard distribution - one for use with a ServletContext, and one without. Once configured, the Web service itself acts like any other Spring wired bean. These Spring beans can be loaded any way desired as Axis2 has no configuration file dependencies from Spring. Spring versions 1.2.6, 1.2.8 and 2.0 have been tested, but probably any version would work as only the core functionality is required. This guide assumes some basic knowledge of Axis2. See the User's Guide for more information.

Configuring Axis2 to be Spring Aware Programming Model From an Axis2 standpoint, two hooks are needed to be placed into the AAR services.xml the ServiceObjectSupplier that hooks Axis2 and Spring together, and the name of the Spring bean that Axis2 will use as the service. All Message Receivers are currently supported, as would be any Message Receiver that extends org.apache.axis2.receivers.AbstractMessageReceiver .

126

Simple Spring Config Example For the purpose of this example, we'll configure Spring via a WAR file's web.xml. Let's add a context-param and a listener: <listener> <listenerclass>org.springframework.web.context.ContextLoaderListener <param-name>contextConfigLocation <param-value>/WEB-INF/applicationContext.xml Next we will show two examples of Spring's /WEB-INF/applicationContext.xml referenced in the web.xml listener - one using a ServletContext, and one without.

With a ServletContext This example (with a ServletContext) applicationContext.xml should be familiar to any Spring user: <property name="myBean" ref="myBean"/> <property name="val" value="Spring, emerge thyself" /> If the service is running in a Servlet Container, i.e., Axis2 will be able to get a hold of the ServletContext, the services.xml for the example would be using SpringServletContextObjectSupplier such as:

<service name="SpringAwareService"> <description> simple spring example <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringServle tContextObjectSupplier <parameter name="SpringBeanName" locked="false">springAwareService

127

<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> While the above example uses RawXMLINOutMessageReceiver as its messageReceiver class, all Message Receivers are currently supported, as would be any Message Receiver that extends org.apache.axis2.receivers.AbstractMessageReceiver .

Without a ServletContext In case Axis2 can't get a ServletContext, (i.e., uses a different transport or is running Axis2 inside the AAR etc,) you have the option of defining a bean that takes advantage of Spring's internal abilities (ApplicationContextAware interface, specifically) to provide an Application Context to Axis2, with a bean ref 'applicationContext' : <property name="myBean" ref="myBean" /> <property name="val" value="Spring, emerge thyself" /> If the service is not running in a Servlet Container, i.e., Axis2 will not be able to get a hold of ServletContext or you prefer not to, the services.xml for the example will be using SpringAppContextAwareObjectSupplier such as:

<service name="SpringAwareService"> <description> simple spring example <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppCon textAwareObjectSupplier

128

<parameter name="SpringBeanName" locked="false">springAwareService <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> While the above example uses RawXMLINOutMessageReceiver as its messageReceiver class, all Message Receivers are currently supported, as would be any Message Receiver that extends org.apache.axis2.receivers.AbstractMessageReceiver . In an environment without a ServletContext, one way you could load the applicationContext.xml file is in a place that will be run once. Upon start-up, execute the following: import org.springframework.context.support.ClassPathXmlApplicationContext; public void createSpringAppCtx(ClassLoader cl) throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {Constants.MY_PATH + "spring/applicationContext.xml"}, false); ctx.setClassLoader(cl); ctx.refresh(); }

Putting It All Together From here, it's just standard Axis2 coding. Only now the service has Spring wiring capabilities. The implementation is the same whether using either SpringServletContextObjectSupplier or SpringAppContextAwareObjectSupplier. The service is as follows: package spring; import import import import import

org.apache.axiom.om.OMAbstractFactory; org.apache.axiom.om.OMElement; org.apache.axiom.om.OMFactory; org.apache.axiom.om.OMNamespace; org.apache.axiom.om.OMText;

public class SpringAwareService { private MyBean myBean = null; //spring 'injects' this implementation public void setMyBean(MyBean myBean) { this.myBean = myBean; }

129

// The web service public OMElement getValue(OMElement ignore) { OMFactory factory= OMAbstractFactory.getOMFactory(); OMNamespace payloadNs= factory.createOMNamespace( "http://springExample.org/example1", "example1"); OMElement payload = factory.createOMElement("string", payloadNs); OMText response = factory.createOMText(this.myBean.emerge()); payload.addChild(response); return payload; } } For those who are new to Spring, one of the ideas is that you program an Interface, as the implementation is pluggable. This idea is referenced in the Spring config file above. Below is the interface: package spring;

/** Interface for Spring aware Bean */ public interface MyBean { String emerge(); }

Here's the implementation: /** Spring wired implementation */ public class MyBeanImpl implements MyBean { String str = null; // spring 'injects' this value public void setVal(String s) { str = s; } // web service gets this value public String emerge() { return str; } } Lastly here's the client - not really necessary for the example, other than for completeness:

130

public class package client; TestClient { private static EndpointReference targetEPR = import java.io.StringWriter; new EndpointReference( import javax.xml.stream.XMLOutputFactory; "http://localhost:8080/axis2/services/SpringAwareService" ); import org.apache.axiom.om.OMAbstractFactory; import /**org.apache.axiom.om.OMElement; import * Simple org.apache.axiom.om.OMFactory; axis2 client. import * org.apache.axiom.om.OMNamespace; import * @param org.apache.axis2.addressing.EndpointReference; args Main import */org.apache.axis2.client.Options; import public org.apache.axis2.client.ServiceClient; static void main(String[] args) { try { OMFactory factory = OMAbstractFactory.getOMFactory(); OMNamespace omNs = factory.createOMNamespace( "http://springExample.org/example1", "example1"); OMElement method = factory.createOMElement("getValue", omNs);

OMElement value = factory.createOMElement("Text", omNs); value.addChild(factory.createOMText(value, "Some String ")); method.addChild(value); ServiceClient serviceClient = new ServiceClient(); Options options = new Options(); serviceClient.setOptions(options); options.setTo(targetEPR); //Blocking invocation OMElement result = serviceClient.sendReceive(method); StringWriter writer = new StringWriter(); result.serialize(XMLOutputFactory.newInstance() .createXMLStreamWriter(writer)); writer.flush();

}

System.out.println("Response: " + writer.toString()); } catch (Exception ex) { ex.printStackTrace(); }

} The examples above assume that both the spring framework .jar and the axis2-spring-*.jar are under WEB-INF/lib. In such a case, the classes shown in this tutorial need to be placed in a JAR under WEB-INF/lib. In this example the JAR layout is: ./mySpring.jar ./META-INF ./META-INF/MANIFEST.MF ./spring ./spring/MyBean.class ./spring/MyBeanImpl.class ./spring/SpringAwareService.class Since all the user classes are in mySpring.jar in this example, the AAR merely contains the services.xml file:

131

./springExample.aar ./META-INF ./META-INF/MANIFEST.MF ./META-INF/services.xml To run this example, make sure you have the axis2-spring*.jar that comes from the axis2std-*-bin distro in the server side WEB-INF/lib, as well as the appropriate Spring jar - most will use the full spring.jar, but the minimum requirements are spring-core, spring-beans, springcontext, and spring-web. When running the client, you should see this output: Response: <example1:string xmlns:example1="http://springExample.org/example1" xmlns:tns="http://ws.apache.org/axis2">Spring, emerge thyself

Spring Inside an AAR Axis2 users frequently want to run Spring inside the AAR. Here we show you how it is done. There are four points to be aware of: (A) You need to configure Spring to use the Axis2 Service Classloader. See the Known issues running Spring inside the AAR area. (B) It's up to you to load Spring, though we give an example below. (C) For reasons such as classloader isolation, the SpringAppContextAwareObjectSupplier is the best choice. (D) The springframework .jar and axis2-spring-*.jar will be placed inside the AAR under the lib directory. Please move the axis2-spring-*.jar from WEB-INF/lib to inside the AAR, as shown below - it will not work otherwise.

The Spring inside an AAR layout ./springExample.aar ./META-INF ./META-INF/MANIFEST.MF ./META-INF/services.xml ./applicationContext.xml ./lib ./lib/axis2-spring-SNAPSHOT.jar ./lib/spring.jar ./spring ./spring/MyBean.class ./spring/MyBeanImpl.class ./spring/SpringAwareService.class ./spring/SpringInit.class As explained in the Without a ServletContext section, the 'Spring inside an AAR' config needs to hook Axis2 and Spring together via a Spring bean. Place the following in your Spring config file:

132

The Spring inside an AAR init class One way to initialize Spring inside the AAR is to org.apache.axis2.engine.ServiceLifeCycle interface. Here we give an example:

use

the

package spring; import org.apache.axis2.engine.ServiceLifeCycle; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.description.AxisService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringInit implements ServiceLifeCycle { /** * This will be called during the deployement time of the service. * irrespective * of the service scope this method will be called */ public void startUp(ConfigurationContext ignore, AxisService service) { try { System.out.println("Starting spring init"); ClassLoader classLoader = service.getClassLoader(); ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"}, false); appCtx.setClassLoader(classLoader); appCtx.refresh(); System.out.println("spring loaded"); } catch (Exception ex) { ex.printStackTrace(); } } /** * This will be called during the system shut down time. * irrespective * of the service scope this method will be called */ public void shutDown(ConfigurationContext ctxIgnore, AxisService ignore) { } }

Here's the services.xml that now includes SpringInit and the SpringAwareService shown above. There is also the composite parameter which is needed when loading Spring in the AAR - see the Known issues running Spring inside the AAR area. <serviceGroup> <service name="SpringAwareService" class="spring.SpringInit"> <description> simple spring example - inside the AAR

133

<parameter name="ServiceTCCL" locked="false">composite <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppCon textAwareObjectSupplier <parameter name="SpringBeanName" locked="false">springAwareService <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>

Known issues running Spring inside the AAR By default, the Axis2 classloader strategy does not permit Spring to run inside the AAR. To allow Spring to run inside the AAR, the 'composite' parameter is used in the services.xml as shown in the example above. There was default behavior of 'composite' in the development cycle in between 1.0 and 1.1, but it resulted in the JIRA issue AXIS2-1214 -problems with getting an initContext.lookup() handle inside the AAR. Spring users typically have little desire to use initContext.lookup(), as they get their Datasources via org.springframework.jdbc.datasource.DriverManagerDataSource in an XML file or with annotations. For EJB home references and the like, Spring provides JndiObjectFactoryBean. While fully testing JndiObjectFactoryBean with EJB has not been done yet (if you do, please send a message to the axis users list) Datasources via Spring inside the AAR have been tested. Basically it works as typically done with Spring, though if you are passing Hibernate XML files you need to put them in a place where Spring will find them. The most flexible way is as follows, using logging in DEBUG mode to see where Spring will look in your jar / class locations:

<property name="mappingLocations"> classpath*:**/MyEntity.hbm.xml ...

Writing Your Own Axis2 Module Axis2 provides extended support for modules (See the Architecture Guide for more details about modules in Axis2). Let's create a custom module and deploy it to MyService, which we created earlier. Send your feedback or questions to: [email protected]. ( Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

Content List •

MyService with a Logging Module •

Step1 : LoggingModule Class



Step2 : LogHandler

134



Step3 : module.xml



Step4: Modify the "axis2.xml"



Step5 : Modify the "services.xml



Step6 : Packaging



Step7 : Deploy the Module in Axis2

The following steps show the actions that need to be performed to deploy a custom module for a given Web service: 1. Create the Module Implementation 2. Create the Handlers 3. Create the module.xml 4. Modify the "axis2.xml" (if you need custom phases) 5. Modify the "services.xml" to engage modules at the deployment time.

6. Package in a ".mar" (Module Archive) 7. Deploy the module in Axis2

MyService with a Logging Module Let's write a simple logging module for our sample located at the "samples\userguide\src" directory of the binary distribution. This module contains one handler that just logs the message that is passed through it. Axis2 uses ".mar" (Module Archive) to deploy modules in Axis2. The following diagram shows the file structure inside which needs to be there in the ".mar" archive. Let's create all these and see how it works.

Step1 : LoggingModule Class LoggingModule is the implementation class of the Axis2 module. Axis2 modules should implement the "org.apache.axis2.modules.Module" interface with the following methods. public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault;//Initialize the module public void shutdown(ConfigurationContext configurationContext) throws AxisFault;//End of module processing public void engageNotify(AxisDescription axisDescription) throws AxisFault; public String[] getPolicyNamespaces() throws AxisFault; public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault ; public boolean canSupportAssertion(Assertion assertion) ;

135

The first three methods can be used to control the module initialization and the termination, and the next three methods are used to perform policy related operations. With the input parameter AxisConfiguration, the user is provided with the complete configuration hierarchy. This can be used to fine-tune the module behavior by the module writers. For a simple logging service, we can keep these methods blank in our implementation class.

Step2 : LogHandler A module in Axis2 can contain, one or more handlers that perform various SOAP header processing at different phases. (See the Architecture Guide for more information on phases). To write a handler one should implement org.apache.axis2.engine.Handler. But for convenience, org.apache.axis2.handlers.AbstractHandler provides an abstract implementation of the Handler interface. For the logging module, we will write a handler with the following methods. "public void invoke(MessageContext ctx);" is the method that is called by the Axis2 engine when the control is passed to the handler. "public void revoke(MessageContext ctx);" is called when the handlers are revoked by the Axis2 engine.

public class LogHandler extends AbstractHandler implements Handler { private static final Log log = LogFactory.getLog(LogHandler.class); private String name; public String getName() { return name; } public InvocationResponse invoke(MessageContext msgContext) throws AxisFault { log.info(msgContext.getEnvelope().toString()); return InvocationResponse.CONTINUE; } public void revoke(MessageContext msgContext) { log.info(msgContext.getEnvelope().toString()); }

}

public void setName(String name) { this.name = name; }

Step3 : module.xml "module.xml" contains the deployment configurations for a particular module. It contains details such as the Implementation class of the module (in this example it is the "LoggingModule" class and various handlers that will run in different phases). The "module.xml" for the logging module will be as follows: <module name="logging" class="userguide.loggingmodule.LoggingModule ">

136

As you can see, there are four flows defined in the "module.xml" 1. inflow - Represents the handler chain that will run when a message is coming in. 2. outflow - Represents the handler chain that will run when the message is going out. 3. Outfaultflow - Represents the handler chain that will run when there is a fault, and the fault is going out. 4. INfaultflow - Represents the handler chain that will run when there is a fault, and the fault is coming in. The following set of tags describe the name of the handler, handler class, and the phase in which this handler is going to run. "InFlowLogHandler" is the name given for the particular instance of this handler class. The value of the class attribute is the actual implementation class for this handler. Since we are writing a logging handler, we can reuse the same handler in all these phases. However, this may not be the same for all the modules. "" describes the phase in which this handler runs. To learn more about Phase rules, check out the article Axis2 Execution Framework

Step 4: Modify the "axis2.xml" In this handler, the "loggingPhase", is defined by the module writer. It is not a pre-defined handler phase, hence the module writer should introduce it to the "axis2.xml" (NOT the services.xml) so that the Axis2 engine knows where to place the handler in different "flows" (inFlow, outFlow, etc.). The following XML lines show the respective changes made to the "axis2.xml" in order to deploy the logging module in the Axis2 engine. This is an extract of the phase section of "axis2.xml".

137



138

The text in green, the custom phase "loggingPhase" is placed in all the flows, hence that phase will be called in all the message flows in the engine. Since our module is associated with this phase, the LogHandler inside the module will now be executed in this phase.

Step5 : Modify the "services.xml" Up to this point, we have created the required classes and configuration descriptions for the logging module, and by changing the "axis2.xml" we created the required phases for the logging module. Next step is to "engage" (use) this module in one of our services. For this, let's use the same Web service that we have used throughout the user's guide- MyService. However, since we need to modify the "services.xml" of MyService in order to engage this module, we use a separate Web service, but with similar operations. The code for this service can be found in the "Axis2_HOME/samples/userguide/src/userguide/example2" directory. The simple changes that we have done to "services.xml' are shown in green in the following lines of xml. <service name="MyServiceWithModule"> <description> This is a sample Web service with a logging module engaged. <module ref="logging"/> <parameter name="ServiceClass" locked="xsd:false">userguide.example2.MyService <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>

In this example, we have changed the service name (the implementation class is very similar to what we have used earlier, although it is in a different package). In addition we have added the line "<module ref="logging"/>" to "services.xml". This informs the Axis2 engine that the module "logging" should be engaged for this service. The handler inside the module will be executed in their respective phases as described by the "module.xml".

Step6 : Packaging Before deploying the module, we need to create the ".mar" file for this module. This can be done, using the "jar" command and then renaming the created .jar file. Else, you can find the "logging.mar" that has already been created in the "Axis2_HOME/samples/userguide" directory.

Step7 : Deploy the Module in Axis2 Deploying a module in Axis2 requires the user to create a directory with the name "modules" in the "webapps/axis2/WEB-INF" directory of their servlet container, and then copying the ".mar" file to that directory. So let's first create the "modules" directory and drop the "logging.mar" into this directory.

Although the required changes to the "services.xml" is very little, we have created a separate 139

service archive (MyServiceWithModule.aar) for users to deploy the service.. Deploy this service using the same steps used in the 'Step 4: Deploy Web Service' sub section in 'Writing a New Service using Codegeneration', and copy the "logging.mar" file to the "modules" directory. Then run directory

'ant

run.client.servicewithmodule'

from

axis2home/samples/userguide

Note: To see the logs, the user needs to modify the "log4j.properties" to log INFO. The property file is located in "webapps/axis2/WEB-INF/classes" of your servlet container. Change the line "log4j.rootCategory= ERROR, LOGFILE" to "log4j.rootCategory=INFO, ERROR, LOGFILE". Note (on samples): All the samples mentioned in the user's guide are located at the "samples\userguide\src" directory of the binary distribution.

ADB Data Binding Axis2 Databinding Framework This document aims to provide an architectural overview of the Axis2 Databinding Framework (referred to as ADB from here onwards) and be a guide to anyone who wants to use and modify ADB. The information is presented under the following topics.

Content •

Introduction



Architectural Overview



Code and Dependencies



Invoking the ADB Code Generator •

As a Stand-alone Schema Compiler



Through the API



Generation Modes



Deep into Generated Code •

An Example!



Known Limitations



Want to Learn More?

Introduction The objective of the Axis2 Databinding framework is to provide a lightweight and simple schema compiler/Java bean generator for Axis2. By no means is it intended to be a fully functional schema compiler like XMLBeans. Note that ADB is written in a fashion that allows it to be used as a stand-alone schema compiler and also to be extended to generate code for other languages.

Architectural Overview ADB is built on a modular architecture that allows it to utilize a pre-configured writer depending on the configuration. The 'big block diagram' for the code generator architecture is

140

depicted below. ADB utilizes the WS-Commons XmlSchema library for reading the Schema. The object model for the schema comes in the form of an XmlSchema object. The schema compiler keeps an instance of the writer (in the default case it's the JavaBeanWriter) which actually writes the classes. The writers may use whatever technique they prefer, in the case of the JavaBeanWriter, it uses an XSLT template. The SchemaCompiler also uses a typemapper object that tells it what classnames to use for the QNames that it encounters. This type mapper is also part of the configuration and the users can override the default type mapper by overriding the property setting.

Code and Dependencies As explained in the previous section, the schema compiler depends on the WS-Commons XmlSchema library. The XSLT transformations are dependent on the JVM's DOM implementation (either Crimson or Xerces) which means that the underlying JVM should be 1.4 or higher. Apart from that ADB has no dependencies on any other special jar files. The code for the schema compiler is completely in the org.apache.axis2.schema.* package. This package resides in the codegen module of the Axis2 source tree. The following are the important classes and files of ADB: 1. SchemaCompiler - The work horse that really compiles the schema into classes. 2. BeanWriter - BeanWriters handle the the actual rendering of the classes. BeanWriter is the interface that writers need to implement in order to be used by the SchemaCompiler. 3. JavaBeanWriter - The default implementation of the BeanWriter interface. 4. TypeMap - represents the interface that the schema compiler uses to find class names for a given QName. 5. JavaTypeMap - the default implementation of the TypeMap 6. ADBBeanTemplate.xsl - the XSLtemplate the JavaBeanWriter uses. 7. Schema-compile.properties - The property file for the schema compiler The easiest way to obtain the ADB binaries is to run the maven build for the Axis2 adbcodegen module. This will generate the axis2-adb-codegen-{$version}.jar inside the target folder which is directly usable when the ADB schema compiler is required. The runtime dependencies for the ADB generated classes is in the Axis2 adb module and the kernal module. Hence to compile and work with the generated classes the axis2-adb{$version}.jar and axis2-kernal-{$version}.jar needs to be in the classpath in addition to other dependencies such as StAX, Axiom, Commons-logging and javax.activation.

Invoking the ADB Code Generator As a Standalone Schema Compiler ADB comes with a XSD2Java code generator that allows the schemas to be compiled just by giving the schema file reference. This main class is presently rather primitive and does not provide much control over the code generation process. This is bound to improve in the near future. XSD2Java accepts the following parameters: 1. The Schema file name - This should be a complete file name pointing to the local file system 2. The output folder name - This should be the name of a folder within the local file

141

system Since the code generator presently has no validations built into it, the compiler is likely to show various error messages if these parameters are not supplied properly.

Through the API This is the only way to harness the full potential of the schema compiler. The current Axis2 integration of ADB happens through this API. The most important classes and methods of the Schema compiler are as follows. •

SchemaCompiler - Constructor

The constructor of the schema compiler expects a CompilerOptions object. This compilerOptions object is more of a holder for the parameters that are passed to the SchemaCompiler. The only mandatory parameter in the CompilerOptions is the output directory. •

SchemaCompiler - Compile(XMLSchema schema)

The compile method to call for a single schema. The expected object is a XMLSchema which is part of the XmlSchema library. •

SchemaCompiler - Compile(List schemaList)

Similar to the previous method but accepts a list of schemas instead of one. For a comprehensive code sample in invoking the schema compiler through the API, the following classes would be helpful. One would also need an understanding of the generation modes of the ADB schema compiler when using it through the API. Hence the following section includes a brief description of the generation modes. •

org.apache.axis2.schema.XSD2Java



org.apache.axis2.schema.ExtensionUtility

Generation Modes ADB extension provides several generation modes for the data bound classes. 1. Integrated Mode In this mode the classes are generated as inner classes of the stub, message receiver or the interface. The ADB framework does not actually write the classes but instead provides a map of DOM document objects that contains the model for the databinding classes. The Axis2 codegen engine in turn parses these documents within its own XSLT parser to create the necessary classes. Implementers are free to use these models differently for their own particular needs. Integrated mode is intended to be used by tool builders. 2. Wrapped Mode In the wrapped mode, the ADB databinder generates one class that contains all the databound classes. This is convenient when the number of classes need to be limited. 3. Expanded Mode This is the usual mode where the code generator generates a class for each of the outer elements and the named complex types. The command line tool (XSD2Java) always generates code in the expanded mode. The rules for generating code (described in the next section) applies regardless of the mode. Switching these modes can be done by passing the correct options via the CompilerOptions object. The following table lists the options and the effects of using them.

142

Field Name in Options

Description

This determines whether to write the output or not. If the flag is on then the classes will be written by ADB. The default is off. This determines whether to wrap the generated classes. If the flag is on wrapClasses then a single class (with adb added to the end of the specified package) will be generated. The default is off. The package name for the mapper class. Please see the advanced mapperClassPackage section for details of the mapper class. The switch that determines whether to switch to helper mode or not. helperMode Please see the advanced section for details of helper mode. A map that stores the namespace name against the package name ns2PackageMap These details are used to override the default packages writeOutput

Deep into Generated Code When the schema compiler is invoked (one-way or another) it generates code depending on the following rules: 1. All named complex types become bean classes. Any attribute or element encapsulated in this complex type will become a field in the generated class. Note that the support for constructs other than xsd:sequence and xsd:all is not yet implemented. 2. All top level elements become classes. This is a rather obvious feature since unless classes are generated for the top level elements the handling of elements becomes difficult and messy! 3. SimpleType restrictions are handled by replacing the relevant type with the basetype Once the code is generated according to the rules it looks like the following. Consider the following schema: <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://soapinterop.org/types" targetNamespace="http://soapinterop.org/types" elementFormDefault="qualified" > <sequence> <element name="varString" type="xsd:string"/> <element name="varInt" type="xsd:int"/> <element name="varFloat" type="xsd:float"/> <element name="myElement" type="tns:SOAPStruct"/> For comprehension let us consider the expanded mode for the code generator. Unless specifically mentioned, the rest of this document assumes that the expanded mode of the code generation is used. This particular schema will generate the following two classes in the designated package, which in this case would be org.soapinterop.types. The package name is derived from the target namespace of the schema. 1. MyElement.java 2. SOAPStruct.java

143

As explained earlier, SOAPStruct refers to the complexType. MyElement is the class that refers to the element. Just as expected, the SOAPStruct bean has getters and setters for varString, varInt and varFloat which are String, int and float respectively. MyElement on the other hand has a single field representing the SOAPStruct object that it encapsulates. The most important aspect of the generated code is that it encapsulates two methods for creating and serializing the beans. Note that to make this work, the generated beans implement the org.apache.axis2.databinding.ADBBean interface The creator and serializer methods look like the following: • public javax.xml.stream.XMLStreamReader getPullParser(javax.xml.namespace.QName qName) This method returns a pull parser that throws the right events for this particular object. However there is a subtle difference between element based classes and complexType based classes 1. An element based bean class (like MyElement.java in the example) will ignore the passed in QName. Instead of using the passed in QName it'll utilize its own QName which is embedded in the class under the constant MY_QNAME, during the code generation. Hence it is usual to call getPullparser() with a null parameter for elements.



2. A ComplexType based bean class (like SOAPStruct.java in the example) will use the passed-in QName to return an instance of the ADBpullparser. This will effectively wrap the elements inside with an element having the passed QName public org.apache.axiom.om.OMElement getOMElement( final javax.xml.namespace.QName parentQName, final org.apache.axiom.om.OMFactory factory){ This method returns an OMElement representing the ADB bean object.



1. Inside the getOMElement method an anonymous ADBDataSource class is created. This anonymous class implements a serialize() method where the serialization logic for that particular bean class is handled. Finally an OMSourcedElementImpl object with the above anonymous class type object as the data source is returned. public static [Object].Factory. parse(javax.xml.stream.XMLStreamReader reader) throws java.lang.Exception This method returns a populated instance of the class in question. Note that [Object] will be replaced by the actual class that contains this method. Say for SOAPStruct the method looks like public static SOAPStruct.Factory. parse(javax.xml.stream.XMLStreamReader reader) throws java.lang.Exception Also note that the above parse method is available in the Factory nested class within the relevant top level class. Hence one will have to get the static Factory instance before calling the parse method.

An Example! Consider the following XML fragment

144

<myElement xmlns="http://soapinterop.org/types"> 5 Hello 3.3 Enthusiastic readers might already have figured out that this XML fragment complies with the Schema mentioned above. The following code snippet shows how to build a populated instance of MyElement with the XML above: XMLStreamReader reader = XMLInputFactory.newInstance(). createXMLStreamReader( new ByteArrayInputStream(xmlString.getBytes())); MyElement elt = MyElement.Factory.parse(reader);

Optionally, the above xml fragment can be reproduced with the following code fragment: OMElement omElement = myElement.getOMElement (MyElement.MY_QNAME, OMAbstractFactory.getSOAP12Factory()); String xmlString = omElement.toStringWithConsume(); Although this example takes on the tedious effort of creating a reader out of a String, inside the Axis2 environment an XMLStreamReader can be directly obtained from the OMElement! Hence, the parse method becomes a huge advantage for hassle free object creation.

Similarly the reader obtained from the object can also be utilized as needed. The following code fragment shows how to utilize the getPullParser method to create an OMElement : XMLStreamReader reader = elt.getPullParser(null); OMElement omElt = new StAXOMBuilder(reader).getDocumentElement(); That's all to it! If you are interested in learning more on ADB the following documents may also be helpful. However, be sure to check the limitations section that follows if you are planning to use ADB for something serious.

Known Limitations ADB is meant to be a 'Simple' databinding framework and was not meant to compile all types of schemas. The following limitations are the most highlighted. 1. Complex Type Extensions and Restrictions.

Want to Learn More? Advanced features of the deserialization and helper mode •

ADB

code

generator

-

explains

xsi:type

based

Tweaking the ADB Code Generator - explains available mechanisms to extend ADB and possibly adopt it to compile schemas to support other languages. •

ADB and Axis2 Integration - explains how the ADB schema compiler was attached to the Axis2 framework •

145

Advanced Axis2 Databinding Framework Features The aim of this section is provide an insight into the newly added advanced features of the Axis2 Databinding (ADB) Framework.

Content •

xsi:type Support



Helper Mode



Additional ADB Topics

xsi:type Support This is implemented by adding a extension mapping class. The code that calls the extension mapper is generated inside the Factory.parse method of the beans and gets activated when the xsi:type attribute is present. The following code fragment shows what the generated type mapper looks like : public static java.lang.Object getTypeObject(java.lang.String namespaceURI, java.lang.String typeName, javax.xml.stream.XMLStreamReader reader) throws java.lang.Exception{ if( "http://soapinterop.org/types".equals(namespaceURI) && "SOAPStruct".equals(typeName)){ return com.test.SOAPStruct.Factory.parse(reader); } throw new java.lang.RuntimeException("Unsupported type " + namespaceURI + " " + typeName); } Inside every Factory.parse method, the extension mapper gets called when a xsi:type attribute is encountered and that type is not the type that is currently being parsed.

The following code fragment shows how the ADB deserialize method calls the mapper class: if (reader.getAttributeValue("http://www.w3.org/2001/XMLSchemainstance","type")!=null){ String fullTypeName = reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type"); if (fullTypeName!=null){ String nsPrefix = fullTypeName.substring(0,fullTypeName.indexOf(":")); nsPrefix = nsPrefix==null?"":nsPrefix; String type = fullTypeName.substring(fullTypeName.indexOf(":")+1); if (!"SOAPStruct".equals(type)){ //find namespace for the prefix String nsUri = reader.getNamespaceContext().getNamespaceURI(nsPrefix); return (SOAPStruct)org.soapinterop.types.ExtensionMapper.getTypeObject( nsUri,type,reader); } } } This makes xsi:type based parsing possible and results in proper xsi:type based serializations at runtime.

146

By default, the mapping package is derived from the targetnamespace of the first schema that is encountered. The package name can also be explicitly set by a CompilerOption:

CompilerOptions compilerOptions = new CompilerOptions(); compilerOptions.setWriteOutput(true); compilerOptions.setOutputLocation(new File("src")); try { SchemaCompiler schemaCompiler = new SchemaCompiler(compilerOptions); XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection(); XmlSchema xmlSchema =xmlSchemaCollection.read(new FileReader("schema/sample.xsd"),null); schemaCompiler.compile(xmlSchema); } catch (Exception e) { e.printStackTrace(); }

Helper mode Helper mode is a fairly new feature. In the helper mode, the beans are plain Java beans and all the deserialization/serialization code is moved to a helper class. For example, the simple schema mentioned in the ADB-howto document will yield four classes instead of the two previously generated: 1. MyElement.java 2. MyElementHelper.java 3. SOAPStruct.java 4. SOAPStructHelper.java The helpers basically contain all the serialization code that otherwise would go into the ADBBeans. Hence the beans in the helper mode are much more simplified. Also note that the helper mode is available only if you are in unpacked mode. The code generator by default does not expand the classes. Helper mode can be switched on by using the setHelperMode method in CompilerOptions:

Additional ADB Topics Tweaking the ADB Code Generator- explains available mechanisms to extend ADB and possibly adopt it to compile schemas to support other languages. •

ADB and Axis2 Integration - explains how the ADB schema compiler was attached to the Axis2 framework •

ADB Integration With Axis2 This document will assist you in writing an extension using the integrator in order to integrate ADB with Axis2.

Content •

Introduction

147



Selection of Generation Modes for ADB



Things to Remember

Introduction ADB Integration with Axis2 is simple and straightforward. Given the extension mechanism of the Axis2 code generator, the obvious choice for the integrator is to write an extension. The extension that is added to support ADB is the SimpleDBExtension (org.apache.axis2.wsdl.codegen.extension.SimpleDBExtension) and can be found in the extensions list of the codegen-config.properties file.

Selection of Generation Modes for ADB The extension sets the options for the code generator via the CompilerOptions, depending on the user's settings. The following table summarizes the use of options. Please refer to the ADB-How to document for the different generation modes and their descriptions.

User parameters Selected code generation parameters None (no parameter other than mandatory ones) wrapClasses=false,writeClasses=false -ss (server side) wrapClasses=false,writeClasses=true -u (unwrap classes) wrapClasses=false,writeClasses=true The following parameters (prefixed with -E) can be used to override these settings manually:

Parameter Name Allowed values Description Sets the write flag. If set to true the classes will be written by r true, false ADB w true, false Sets the wrapping flag. if true the classes will be wrapped. Note that these parameters have no corresponding long names and MUST be prefixed with a -E to be processed by the code generator. For example: WSDL2Java .... -Er true

Things to Remember 1. SimpleDBExtension is for the ADB databinding framework only and will process requests only when this framework is specified during code generation (using the switch -d adb). In the most recent release, the default has been set as ADB and hence if the -d option is missing then the databinding framework will be ADB.

ADB Tweaking Guide This document explains the mechanisms available to extend ADB and possibly adopt it to compile schemas to support other languages.

Content •

Introduction



Know the Configuration



The First Tweak - Generate Plain Java Beans

148



A More Advanced Tweak - Generate Code for Another Language

Introduction ADB was written with future extensibility in mind, with a clear and flexible way to extend or modify its functionality. Available mechanisms to extend ADB and possibly adopt it to compile schemas to support other languages are described below.

Know the Configuration The configuration for the ADB framework is in the schema-compile.properties file found in the org.apache.axis2.schema package. This properties file has the following important properties •

schema.bean.writer.class

This is the writer class. This is used by the schema compiler to write the beans and should implement the org.apache.axis2.schema.writer.BeanWriter interface. The schema compiler delegates the bean writing task to the specified instance of the BeanWriter. •

schema.bean.writer.template

This specifies the template to be used in the BeanWriter. The BeanWriter author is free to use any mechanism to write the classes but the default mechanism is to use a xsl template. This property may be left blank if the BeanWriter implementation does not use a template. •

schema.bean.typemap

This is the type map to be used by the schema compiler. It should be an implementation of the org.apache.axis2.schema.typemap.TypeMap interface. The default typemap implementation encapsulates a hashmap with type QName to Class name string mapping.

The First Tweak - Generate Plain Java Beans The first, most simple tweak for the code generator could be to switch to plain bean generation. The default behavior of the ADB framework is to generate ADBBeans, but most users, if they want to use ADB as a standalone compiler, would prefer to have plain java beans. This can in fact be done by simply changing the template used. The template for plain java beans is already available in org.apache.axis2.schema.template package. To make this work replace /org/apache/axis2/databinding/schema/template/ADBBeanTemplate.xsl with /org/apache/axis2/databinding/schema/template/PlainBeanTemplate.xsl in schema-compile.properties.

the the the the

Congratulations! You just tweaked ADB to generate plain java beans. To generate custom formats, the templates need to be modified. The schema for the xml generated by the JavaBeanWriter is available in the source tree under the Other directory in the codegen module. Advanced users with knowledge of XSLT can easily modify the templates to generate code in their own formats.

A More Advanced Tweak - Generate Code for Another Language To generate code for another language, there are two main components that need to be

149

written. •

The BeanWriter

Implement the BeanWriter interface for this class. A nice example is the org.apache.axis2.schema.writer.JavaBeanWriter which has a lot of reusable code. In fact if the target language is object-oriented (such as C# or even C++), one would even be able to extend the JavaBeanWriter itself. •

The TypeMap

Implement the TypeMap interface for this class. The org.apache.axis2.schema.typemap.JavaTypeMap class is a simple implementation for the typemap where the QName to class name strings are kept inside a hashmap instance. This technique is fairly sufficient and only the type names would need to change to support another language. Surprisingly, this is all that needs to be done to have other language support for ADB. Change the configuration and you are ready to generate code for other languages! This tweaking guide is supposed to be a simple guideline for anyone who wishes to dig deep into the mechanics of the ADB code generator. Users are free to experiment with it and modify the schema compiler accordingly to their needs. Also note that the intention of this section is not to be a step by step guide to custom code generation. Anyone who wish to do so would need to dig into the code and get their hands dirty!

JiBx Data Binding JiBX Integration With Axis2 This document describes using JiBX data binding with Axis2. JiBX differs from the other data binding techniques supported by Axis2 in that it allows you to use your own Java data objects (as opposed to Java data objects generated from a schema definition). JiBX also provides a nicer form of unwrapped Web services interface than is supported by the other data binding techniques. On the downside, JiBX requires more setup than the other data binding techniques - in particular, you need to come up with a set of data classes and a binding definition in order to work with JiBX in Axis2. JiBX support for Axis2 and Web services in general is continuing to evolve. This page covers the basics of using JiBX with Axis2 as of the current release. Check the JiBX Axis2 Wiki page for updated information about using JiBX with Axis2.

Content •

Introduction



Wrapped vs. unwrapped



Starting from Java



Starting from WSDL



Axis2 JiBX Code Generation



Coming Attractions

Introduction JiBX data binding supports fast and flexible conversions between plain old Java objects (POJOs) and XML. JiBX uses a mapped binding approach that's based on binding definition

150

documents you provide. This approach let's you customize the way your Java objects are converted to and from XML. You can even define multiple bindings to use the same Java objects with different XML representations. These features make JiBX especially useful if you're developing a Web service based on existing Java code, or when you need to support multiple XML representations for a Web service (as when you're using versioned schema definitions). Axis2 supports using JiBX with your Web services, including generating the necessary linkage code for both client and server sides. However, the Axis2 support for JiBX does not currently include code generation from the schema for a Web service - you need to provide your own data classes and JiBX binding definition, and you also need to make sure that the binding definition matches the XML structures defined for your Web service. The JiBX project provides some basic tools to help with code generation from schema, binding generation from Java classes, and schema generation from the combination of Java classes and a binding definition. In the future, improved versions of these tools will be integrated directly into the Axis2 framework support, but for now you're on your own with this part of the setup. You can use JiBX data binding both to expose existing Java code as a service, and to build a client for an existing service. This document runs through the sequence of steps involved for each of these cases, just to help users understand the basic approach to working with JiBX in Axis2. You can find full instructions on the standard JiBX parts of this sequence on the JiBX Web site.

Wrapped vs. unwrapped Axis2 support for JiBX currently only works with the document-literal (doc/lit) form of Web services definitions. Doc/lit Web services generally use particular schema elements as input and output from each operation, and the Axis2 support for JiBX assumes this structure (which is also the structure required for compatibility with the WS-I Basic Profile). A popular subset of doc/lit Web services use a form called "wrapped". Wrapped doc/lit Web services define service operations that correspond to method calls, using input and output element names based on the method name and embedding the actual parameter values for the method call within the input element. When used with Axis2, JiBX supports both general doc/lit and wrapped service definitions. Wrapped service definitions can be "unwrapped" during code generation to provide a greatly simplified interface. JiBX unwrapping of service definitions is not compatible with the unwrapping support for other data binding frameworks used with Axis2, but most users will find the JiBX approach easy and convenient. See the JiBX Unwrapped Example and the JiBX Document/Literal Example pages for a detailed comparison of the two forms of service interface.

Starting from Java Here's the sequence of steps for using JiBX with Axis2 to expose existing Java code as a Web service: 1. Create a JiBX binding definition for the data being transferred by the Web service (you may be able to use the JiBX binding generator to help with this step). 2. Create a schema that matches the XML defined by your binding (you may be able to use the JiBX schema generator to help with this). If you're using a wrapped form of interface to your service you'll also need to create schema definitions for the wrapper input and output elements used by each operation. 3. Create a WSDL document for your service, with the schema embedded or imported. 4. Generate Axis2 server-side linkage code using WSDL2Java with the WSDL and your binding definition. 5. Run the JiBX binding compiler on your Java classes to add the actual binding code.

151

6. Include the axis2-jibx.jar in your runtime classpath, along with the jibx-runtime.jar. If you use a wrapped interface for your Web service you can expose method calls in your existing code directly as operations in the service. In this case you normally just use your existing data objects with JiBX data binding, and add schema definitions for the wrapper elements. See the JiBX Unwrapped Example page for more details on how this works. If you use a non-wrapped interface for your Web service you need to define classes to hold the data input and output from each operation. In this case these holder classes need to be included in the JiBX binding definition. See the JiBX Document/Literal Example page for more details on this case.

Starting from WSDL Here's the sequence of steps for using JiBX with Axis2 to implement a client for an existing Web service (or the actual service, when you've been supplied with the WSDL your service is to implement): 1. Create Java classes for the data being transferred by the Web service, and a JiBX binding definition that maps these classes to the schema defined by the Web service (you may be able to use the JiBX xsd2jibx tool to help with this). 2. Generate Axis2 client linkage code using WSDL2Java with the WSDL and your binding definition. 3. Run the JiBX binding compiler on your Java classes to add the actual binding code. 4. Include the axis2-jibx.jar in your runtime classpath, along with the jibx-runtime.jar As with the starting from Java case, there are some differences in the handling depending on whether your service definition fits the wrapped form. See the JiBX Unwrapped Example and JiBX Document/Literal Example pages for more details.

WSDL2Java usage To run the WSDL2Java tool for JiBX data binding you need: 1. To specify -d jibx to select JiBX binding. 2. You also generally need an additional parameter, -Ebindingfile {file} (where {file} is the file path to your JiBX binding definition). 3. Finally, you need to have the axis2-jibx-XXXX.jar, the jibx-bind-XXXX.jar, and the jibx-run-XXXX.jar files from your Axis2 distribution included in the WSDL2Java classpath. If you want to use the unwrapped form of interface you also need to specify the -uw option to WSDL2Java. In this case your JiBX binding definition must include abstact mappings for all the complex objects which correspond to method parameters, and each abstract mapping must specify a type-name attribute that matches the schema complexType used in the WSDL. You can also use formats in the binding definition to define the handling of schema simpleTypes. Schema types corresponding to Java primitives and simple objects with built-in JiBX conversions are handled automatically, and if all the parameter and return values in your wrapped WSDL are of these types you don't even need a JiBX binding definition. This is the one case where the -Ebindingfile {file} parameter is not needed. If you're not unwrapping the interface, you must use a JiBX binding definition and it must include a concrete mapping for each element used as input or output by any operation.

Coming Attractions Work is in-progress on better tools to support generating Java classes and corresponding

152

JiBX binding definitions from an input schema, and also for generating binding+schema generation from existing code. These features will be integrated into the Axis2 JiBX support when they are available. Check the JiBX project site for updates on JiBX, and the JiBX Axis2 Wiki page for updated information about using JiBX with Axis2.

References JiBX: Bindings Tutorial

JiBX general document/literal Code generation for JiBX data binding converts operations defined by a Web service to method calls. With general document/literal (doc/lit) Web services the generated methods each take a single parameter object and return a single result object. Here's a sample doc/lit WSDL (partial) by way of an example: <wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl" xmlns:tns="http://ws.sosnoski.com/library/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"> <wsdl:types> <schema elementFormDefault="qualified" targetNamespace="http://ws.sosnoski.com/library/types" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="getBook"> <sequence> <element name="isbn" type="string"/> <element name="getBookResponse"> <sequence> <element name="book" minOccurs="0" type="tns:BookInformation"/> <element name="addBook"> <sequence> <element name="type" type="string"/> <element name="isbn" type="string"/> <element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/> <element name="title" type="string"/>

153

<element name="addBookResponse"> <sequence> <element name="success" type="boolean"/> <sequence> <element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/> <element name="title" type="string"/> <wsdl:message name="getBookRequest"> <wsdl:part element="wns:getBook" name="parameters"/> <wsdl:message name="getBookResponse"> <wsdl:part element="wns:getBookResponse" name="parameters"/> <wsdl:message name="addBookRequest"> <wsdl:part element="wns:addBook" name="parameters"/> <wsdl:message name="addBookResponse"> <wsdl:part element="wns:addBookResponse" name="parameters"/> <wsdl:portType name="Library"> <wsdl:operation name="getBook"> <wsdl:input message="wns:getBookRequest" name="getBookRequest"/> <wsdl:output message="wns:getBookResponse" name="getBookResponse"/> <wsdl:operation name="addBook"> <wsdl:input message="wns:addBookRequest" name="addBookRequest"/> <wsdl:output message="wns:addBookResponse" name="addBookResponse"/> ... This WSDL defines a service with just two operations: getBook and addBook. The getBook operation takes a getBook element as input, and returns a getBookResponse element as output, while addBook takes an addBook element as input and returns an addBookResponse as output. Here's the body of the client interface generated by the standard

154

JiBX code generation: public interface LibraryJibxUnwrapped { /** * Auto generated method signatures * @param addBook */ public com.sosnoski.ws.library.jibx.wrappers.AddBookResponse addBook( com.sosnoski.ws.library.jibx.wrappers.AddBookRequest addBook) throws java.rmi.RemoteException; /** * Auto generated method signatures * @param getBook */ public com.sosnoski.ws.library.jibx.wrappers.GetBookResponse

getBook(

com.sosnoski.ws.library.jibx.wrappers.GetBookRequest getBook) throws java.rmi.RemoteException; } You can see that the JiBX code generation converted the operations into simple method call interfaces using objects corresponding to the input and output elements of the operation (see JiBX Unwrapped Example for the interface generated when unwrapping is instead used). The server-side interface is the same. You need to supply an appropriate JiBX binding definition for use in code generation (using the -Ebindingfile {file} parameter for WSDL2Java - see JiBX Codegen Integration - WSDL2Java usage for more details). This must define concrete mappings for each element used as the input or output of an operation. The JiBX code generation extension matches the element names to the binding in order to determine the corresponding class to use in generated code. For example, here's a binding definition that matches the above WSDL: <mapping name="getBook" class="com.sosnoski.ws.library.jibx.wrappers.GetBookRequest"> <mapping name="getBookResponse" class="com.sosnoski.ws.library.jibx.wrappers.GetBookResponse"> <structure name="book" field="m_book"/> <mapping name="addBook" class="com.sosnoski.ws.library.jibx.wrappers.AddBookRequest"> <structure field="m_book">

155

<mapping name="addBookResponse" class="com.sosnoski.ws.library.jibx.wrappers.AddBookResponse"/> <mapping abstract="true" class="com.sosnoski.ws.library.jibx.beans.Book">
And here are the actual data object classes: package com.sosnoski.ws.library.jibx.wrappers; import com.sosnoski.ws.library.jibx.beans.Book; public class AddBookRequest { private Book m_book; public AddBookRequest(Book book) { m_book = book; }

}

public Book getBook() { return m_book; }

public class AddBookResponse { } public class GetBookRequest { private String m_isbn; public GetBookRequest(String isbn) { m_isbn = isbn; } public String getIsbn() { return m_isbn; } }

156

public class GetBookResponse { private Book m_book; public GetBookResponse(Book book) { m_book = book; }

}

public Book getBook() { return m_book; }

package com.sosnoski.ws.library.jibx.beans; public class Book { private String m_type; private String m_isbn; private String m_title; private String[] m_authors; public Book() {} public String getType() { return m_type; } public String getIsbn() { return m_isbn; } public String getTitle() { return m_title; }

}

public String[] getAuthors() { return m_authors; }

JiBX Unwrapped document/literal Code generation for JiBX data binding converts operations defined by a Web service to method calls. In the most general case of document/literal (doc/lit) Web services the generated methods each take a single parameter object and return a single result object. This type of interface can be painful for developers because it adds both a layer of indirection and potentially a large number of extra classes (one input and one output class for each generated method). Fortunately, there's an alternative way of generating methods that gives a much more usable API for many Web services. This alternative is called unwrapping, and the service definitions that it applies to are called wrapped definitions. The key difference that qualifies a service definition as wrapped is the structure of the input and output elements used for operations. Here's a sample wrapped WSDL (partial) by way of an example:

157

<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl" xmlns:tns="http://ws.sosnoski.com/library/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"> <wsdl:types> <schema elementFormDefault="qualified" targetNamespace="http://ws.sosnoski.com/library/types" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="getBook"> <sequence> <element name="isbn" type="string"/>

<wsdl:message name="getBookRequest"> <wsdl:part element="wns:getBook" name="parameters"/> <wsdl:message name="getBookResponse"> <wsdl:part element="wns:getBookResponse" name="parameters"/> <element name="getBookResponse"> <wsdl:message name="addBookRequest"> <sequence> <wsdl:part element="wns:addBook" name="parameters"/> <element name="book" minOccurs="0" type="tns:BookInformation"/> <wsdl:message name="addBookResponse"> <wsdl:part element="wns:addBookResponse" name="parameters"/> <element name="addBook"> <wsdl:portType name="Library"> <sequence> <element name="type" type="string"/> <wsdl:operation name="getBook"> <element name="isbn" type="string"/> <wsdl:input message="wns:getBookRequest" name="getBookRequest"/> <element name="author" minOccurs="0" maxOccurs="unbounded" <wsdl:output message="wns:getBookResponse" type="string"/> name="getBookResponse"/> <element name="title" type="string"/> <wsdl:operation name="addBook"> <wsdl:input message="wns:addBookRequest" name="addBookRequest"/> <wsdl:output message="wns:addBookResponse" <element name="addBookResponse"> name="addBookResponse"/> <sequence> <element name="success" type="boolean"/> ... <sequence> <element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/> <element name="title" type="string"/> 158

This WSDL defines a service with just two operations: getBook and addBook. The getBook operation takes a getBook element as input, and returns a getBookResponse element as output, while addBook takes an addBook element as input and returns an addBookResponse as output. Each of these input and output elements in turn consists of a sequence of child elements, with some of the child elements defined directly using standard schema types and others referencing user-defined schema types. As I said up front, this WSDL qualifies for unwrapped handling using JiBX. Here's the body of the client interface generated when using unwrapping (the -uw option for WSDL2Java): public interface LibraryJibxUnwrapped { /** * Auto generated method signatures * @param type* @param isbn* @param author* @param title */ public boolean addBook( java.lang.String type,java.lang.String isbn,java.lang.String[] author,java.lang.String title) throws java.rmi.RemoteException; /** * Auto generated method signatures * @param isbn */ public com.sosnoski.ws.library.jibx.beans.Book getBook( java.lang.String isbn) throws java.rmi.RemoteException; } You can see that the JiBX code generation converted the operations into simple method call interfaces without introducing any extraneous objects (see JiBX Document/Literal Example for the interface generated when unwrapping is not used). The server-side interface is the same. The key points that allow unwrapped handling with JiBX are: 1. Each operation either accepts no input, or the input consists of a single element. 2. Each input element is defined as a schema complexType consisting of a sequence of any number of child elements. 3. Each operation either generates no output, or the output consists of a single element. 4. Each output element is defined as a schema complexType consisting of a sequence that's either empty or contains a single child element. 5. The child elements of both inputs and outputs are defined using type references, rather than an embedded type definitions. You also need to supply an appropriate JiBX binding definition (using the -Ebindingfile {file} parameter for WSDL2Java - see JiBX Codegen Integration - WSDL2Java usage for more details). This must define abstract mappings for the complexTypes referenced by child elements of the inputs and outputs, with a type-name attribute matching the schema complexType name. If the child elements reference schema simpleType definitions the binding must also define a formats for each simpleType, with a label attribute matching the schema simpleType name. The binding definition must also specify the force-classes='true' attribute on the binding element. For example, here's a binding definition that matches the above WSDL:

159

<mapping abstract="true" class="com.sosnoski.ws.library.jibx.beans.Book" type-name="tns:BookInformation"> And here's the actual com.sosnoski.ws.library.jibx.beans.Book class:

public String getIsbn() { package com.sosnoski.ws.library.jibx.beans; return m_isbn; public class Book { } private String m_type; private String m_isbn; public privateString StringgetTitle() m_title; { return m_title; private String[] m_authors; } public Book() {} public String[] getAuthors() { return m_authors; public String getType() { return m_type; } } } The JiBX code generation for Axis2 currently requires that classes coresponding to unwrapped child elements (such as com.sosnoski.ws.library.jibx.beans.Book, in this case) provide public default (no-argument) constructors. JiBX handling allows the child elements of both inputs and outputs to be optional (with nillable='true', minOccurs='0', or both), providing the binding converts these child elements to object types rather than primitive types. It also allows repeated child elements (with minOccurs='unbounded', or any value of minOccurs greater than one), representing the repeated elements as arrays of the corresponding object or primitive types.

Advanced Writing Web Services Using Apache Axis2's Primary APIs Apache Axis2 dispatches a component called MessageReceiver when Receiving a Message to the server. Apache Axis2 provides different implementations of this class and it can be configured by adding a messageReceiver tag to services.xml. Apache Axis2 provides an implementation for a class of Message receivers called RawXml Message receivers. They work at the XML level and can only handle OMElements as parameters. This section explains how to write a service using them.

160

In our example, the Web service will have two operations. public void ping(OMElement element){} //IN-ONLY op, just accepts the OMElement and does some processing. public OMElement echo(OMElement element){} //IN-OUT op, accepts an OMElement and sends back the same again

How to Write a Web Service? Writing a new Web service with Apache Axis2 involves four steps: 1. Write the Implementation Class. 2. Write a services.xml file to explain the Web service. 3. Create a *.aar archive (Axis Archive) for the Web service. 4. Deploy the Web service.

Step1: Write the Implementation Class An implementation class has the business logic for the Web service and implements the operations provided by the Web service. Unless you have data binding, the signature of the methods can have only one parameter of the type OMElement. For more details on OMElement see the OM Tutorial. public class MyService{ public void ping(OMElement element){ // Business Logic ...... } public OMElement echo(OMElement element){ ...... } }

Step2: Write the services.xml file "services.xml" has the configuration for a Web service. Each Web service, deployed in Apache Axis2 , must have its configuration in "services.xml". The configuration for MyService is as follows:

161

<service > <description> This is a sample Web service with two operations, echo and ping. <parameter name="ServiceClass" locked="false">userguide.example1.MyService <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> urn:echo <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> urn:ping The above XML tags can be explained as follows: 1. The description of the service class is provided in the description tag. <service > <description> This is a sample Web service with two operations, echo and ping. 2. The name of the service class is provided as a parameter. <parameter name="serviceClass" locked="false"> userguide.example1.MyService

3. The "operation" XML tag describes the operations that are available in this service with respective message receivers. <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> urn:echo <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> urn:ping 4. Every operation must map to a corresponding MessageReceiver class. After a message is processed by the handlers, the Axis2 engine hands it over to a MessageReceiver. 5. For the "echo" operation, we have used a RawXMLINOutMessageReceiver since it is an IN-OUT operation. For the IN-ONLY operation "ping", we have used RawXMLINOnlyMessageReceiver as the message receiver. 6. The actionMapping is required only if you want to enable WS-Addressing. This will be used later in this user guide.

162

7. You can write a services.xml file to include a group of services instead of a single service. This makes the management and deployment of a set of related services very easy. At runtime, you can share information between these services within a single interaction using the ServiceGroupContext. If you hope to use this functionality, the services.xml file should have the following format. <ServiceGroup> <service name="Service1"> <service name="Service2"> <module ref="ModuleName" /> <parameter name="serviceGroupParam1" locked="false">value 1 Note : The name of the service is a compulsory attribute.

Step3: Create the Web Service Archive Apache Axis2 uses the ".aar" (Axis Archive) file as the deployment package for Web services. Therefore, for MyService we will use "MyService.aar" with the "services.xml" packaged in the META-INF in the directory structure shown below. Please note that the name of the archive file will be the same as that of the service only if the services.xml contains only one service element.

To create the archive file, you can create a .jar file containing all the necessary files and then rename it to a .aar file. This archive file can be found in the "Axis2_HOME/samples/userguide" directory. This file has to be deployed now.

Step4: Deploy the Web Service The service can be deployed by dropping the ".aar" file into the "services" directory in "/webapps/axis2/WEB-INF" of your servlet container. Start the servlet container (if you have not already started), click the link "Services" on the Home Page of Axis2 Web Application (http://localhost:8080/axis2) and see whether MyService is deployed properly. If you can see the following output, then you have successfully deployed MyService on Apache Axis2. Congratulations !!

163

Note: Apache Axis2 provides an easy way to deploy Web services using the "Upload Service" tool on the Axis2 Web Application's Administration module. Please refer to the Web Administration Guide for more information.

Writing Web Service Clients Using Axis2's Primary APIs This section presents a complex yet powerful XML based client API, which is intended for advanced users. However, if you are a new user, we recommend using code generation given in the Advance User's Guide. Web services can be used to provide a wide-range of functionality to the user from simple, quick operations such as "getStockQuote" to time consuming business services. When we utilize (invoke using client applications) these Web services, we cannot use simple generic invocation paradigms that suite all the timing complexities involved in the service operations. For example, if we use a single transport channel (such as HTTP) to invoke a Web service with an IN-OUT operation that takes a long time to complete, then most often we may end up with "connection time outs". On the other hand, if there are simultaneous service invocations that we need to perform from a single client application, then the use of a "blocking" client API will degrade the performance of the client application. Similarly, there are various other

164

consequences such as One-Way transports that come into play when we need them. Let's try to analyze some common service invocation paradigms. Many Web service engines provide users with Blocking and Non-Blocking client APIs. Blocking API - Once the service invocation is called, the client application hangs and only regains control when the operation completes, after which the client receives a response or a fault. This is the simplest way of invoking Web services, and it also suites many business situations. •

Non-Blocking API - This is a callback or polling based API. Hence once a service invocation is called, the client application immediately regains control and the response is retrieved using the callback object provided. This approach provides flexibility to the client application to invoke several Web services simultaneously without blocking the operation already invoked. •

Both mechanisms work at the API level. Let's name the asynchronous behavior that we can get using the Non-Blocking API as API Level Asynchrony. Both mechanisms use single transport connections to send the request and to receive the response. They severely lag the capability of using two transport connections for the request and the response (either One-Way or Two-Way). So both these mechanisms fail to address the problem of long running transactions (the transport connection may time-out before the operation completes). A possible solution would be to use two separate transport connections for request and response. The asynchronous behavior that we gain using this solution can be called Transport Level Asynchrony. By combining API Level Asynchrony and Transport Level Asynchrony, we can obtain four different invocation patterns for Web services as shown in the following table. API

Dual Transports? Description

Blocking

No

The simplest and more familiar invocation pattern

Non-Blocking No

Using callbacks or polling

Blocking

This is useful when the service operation is IN-OUT in nature but the transport used is One-Way (e.g. SMTP)

Yes

Non-Blocking Yes

This is can be used to gain the maximum asynchronous behavior. Non blocking at the API level and also at the transport level.

Axis2 provides the user with all these possibilities to invoke Web services. The following section presents clients that use the different possibilities presented above to invoke a Web Service using ServiceClients. All the samples mentioned in this guide are located at the "samples\userguide\src" directory of the binary distribution. This section presents four types of clients. 1. Request-Response, Blocking Client 2. One Way Client 3. Request-Response, Non-Blocking that uses one transport connection 4. Request-Response, Non-Blocking that uses two transport connections

165

Request-Response, Blocking Client Axis2 blocking how we blocking

provides the user with several invocation patterns for Web services, ranging from pure single channel invocations to non-blocking dual channel invocations. First let us see can write a client to invoke the "echo" operation of "MyService" using the simplest invocation. The client code you need to write is as follows.

try { OMElement payload = ClientUtil.getEchoOMElement(); Options options = new Options(); options.setTo(targetEPR); // this sets the location of MyService service ServiceClient serviceClient = new ServiceClient(); serviceClient.setOptions(options); OMElement result = serviceClient.sendReceive(payload); System.out.println(result); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } 1. The lines highlighted in green show the set of operations that you need to perform in order to invoke a Web service. 2. The rest is used to create the OMElement that needs to be sent and display the response OMElement. To test this client, use the provided Ant build file that can be found in the "Axis2_HOME/samples/userguide" directory. Run the "run.client.blocking" target. If you can see the response OMElement printed in your command line, then you have successfully tested the client.

One Way Client In the Web service "MyService", we had an IN-ONLY operation with the name "ping" (see Creating a New Web Service). Let's write a client to invoke this operation. The client code is as follows:

166

try { OMElement payload = ClientUtil.getPingOMElement(); Options options = new Options(); options.setTo(targetEPR); ServiceClient serviceClient = new ServiceClient(); serviceClient.setOptions(options); serviceClient.fireAndForget(payload); /** * We have to block this thread untill we send the request , the problem * is if we go out of the main thread , then request wont send ,so * you have to wait some time :) */ Thread.sleep(500); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } Since we are accessing an IN-ONLY operation, we can directly use the fireAndForget() in the ServiceClient to invoke this operation. This will not block the invocation and will return the control immediately back to the client. You can test this client by running the target "run.client.ping" of the Ant build file at "Axis2Home/samples/userguide". We have now invoked the two operations in our service. Are we done? No! There's a lot more to explore. Let's see some other ways to invoke the same operations.

Request-Response, Non-Blocking that uses one transport connection In the "EchoBlockingClient" once the serviceClient.sendReceive(payload); is called, the client is blocked till the operation is complete. This behavior is not desirable when there are many Web service invocations to be done in a single client application or within a GUI. A solution would be to use a Non-Blocking API to invoke Web services. Axis2 provides a callback based non-blocking API for users. A sample client for this can be found under "Axis2_HOME/samples/userguide/src/userguide/clients" with the name "EchoNonBlockingClient". If we consider the changes that users may have to do with respect to the "EchoBlockingClient" that we have already seen, it will be as follows: ●

serviceClient.sendReceiveNonblocking(payload, callback);

The invocation accepts a callback object as a parameter. Axis2 client API provides an abstract Callback with the following methods: public abstract void onComplete(AsyncResult result); public abstract void onError(Exception e); public boolean isComplete() {} The user is expected to implement the "onComplete " and "onError " methods of their extended call back class. The Axis2 engine calls the "onComplete" method once the Web service response is received by the Axis2 Client API (ServiceClient). This will eliminate the blocking nature of the Web service invocation and provide users with the flexibility to use Non Blocking API for Web service Clients. To run the sample client ("EchoNonBlockingClient") run.client.nonblocking target of the Ant "Axis2_HOME/samples/userguide" directory.

167

you file

can simply use found in

the the

Request-Response, Non-Blocking that uses two transport connections The solution provided by the Non-Blocking API has one limitation when it comes to Web service invocations that take a long time to complete. The limitation is due to the use of single transport connections to invoke the Web service and retrieve the response. In other words, client API provides a non-blocking invocation mechanism for users, but the request and the response come in a single transport (Two-Way transport) connection (like HTTP). Long running Web service invocations or Web service invocations using One-Way transports (like SMTP) cannot be utilized by simply using a non-blocking invocation. The trivial solution is to use separate transport connections (either One-Way or Two-Way) for the request and response. The next problem that needs to be solved is the correlation (correlating the request and the response). WS-Addressing provides a neat solution to this using <wsa:MessageID> and <wsa:RelatesTo> headers. Axis2 provides support for an addressing based correlation mechanism and a complying Client API to invoke Web services with two transport connections. (The core of Axis2 does not depend on WS-Addressing, but contains a set of parameters, like in addressing, that can be populated by any method. WSAddressing is one of the uses that may populate them. Even the transports can populate them. Hence, Axis2 has the flexibility to use different versions of addressing) Users can select between Blocking and Non-Blocking APIs for the Web service clients with two transport connections. By simply using a boolean flag, the same API can be used to invoke Web services (IN-OUT operations) using two separate transport connections. Let's see how it's done using an example. The following code fragment shows how to invoke the same "echo" operation using Non-Blocking API with two transport connections. The ultimate asynchrony!!

try { OMElement payload = ClientUtil.getEchoOMElement(); Options options = new Options(); options.setTo(targetEPR); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); options.setUseSeparateListener(true); options.setAction("urn:echo"); // this is the action mapping we put within the service.xml //Callback to handle the response Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println(result.getResponseEnvelope()); } public void onError(Exception e) { e.printStackTrace(); } };

168

//Non-Blocking Invocation sender = new ServiceClient(); sender.engageModule(new QName(Constants.MODULE_ADDRESSING)); sender.setOptions(options); sender.sendReceiveNonBlocking(payload, callback); //Wait till the callback receives the response. while (!callback.isComplete()) { Thread.sleep(1000); } //Need to close the Client Side Listener. } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } finally { try { sender.cleanup(); } catch (AxisFault axisFault) { //have to ignore this } } The boolean flag (value True) in the options.setUseSeparateListener(...) method informs the Axis2 engine to use separate transport connections for the request and response. Finally sender.cleanup() informs the Axis2 engine to stop the client side listener, which started to retrieve the response. To run the sample client ("EchoNonBlockingDualClient") "run.client.nonblockingdual" target of the Ant "Axis2_HOME/samples/userguide/" directory.

you file

can simply use found in

the the

Handling Binary Data with Axis2 (MTOM/SwA) This document describes how to use the Axis2 functionality to send/receive binary data with SOAP.

Content •

Introduction •



Where Does MTOM Come In?

MTOM with Axis2 •

Programming Model



Enabling MTOM Optimization at Client Side



Enabling MTOM Optimization at Server Side



Accessing Received Binary Data (Sample Code)





Service



Client

MTOM Databinding •



Using ADB

SOAP with Attachments with Axis2

169





Sending SwA Type Attachments



Receiving SwA Type Attachments



MTOM Backward Compatibility with SwA

Advanced Topics •

File Caching for Attachments

Introduction Despite the flexibility, interoperability, and global acceptance of XML, there are times when serializing data into XML does not make sense. Web services users may want to transmit binary attachments of various sorts like images, drawings, XML docs, etc., together with a SOAP message. Such data is often in a particular binary format. Traditionally, two techniques have been used in dealing with opaque data in XML; 1. "By value" Sending binary data by value is achieved by embedding opaque data (of course after some form of encoding) as an element or attribute content of the XML component of data. The main advantage of this technique is that it gives applications the ability to process and describe data, based only on the XML component of the data. XML supports opaque data as content through the use of either base64 or hexadecimal text encoding. Both techniques bloat the size of the data. For UTF-8 underlying text encoding, base64 encoding increases the size of the binary data by a factor of 1.33x of the original size, while hexadecimal encoding expands data by a factor of 2x. The above factors will be doubled if UTF-16 text encoding is used. Also of concern is the overhead in processing costs (both real and perceived) for these formats, especially when decoding back into raw binary. 2. "By reference" Sending binary data by reference is achieved by attaching pure binary data as external unparsed general entities outside the XML document and then embedding reference URIs to those entities as elements or attribute values. This prevents the unnecessary bloating of data and wasting of processing power. The primary obstacle for using these unparsed entities is their heavy reliance on DTDs, which impedes modularity as well as the use of XML namespaces. There were several specifications introduced in the Web services world to deal with this binary attachment problem using the "by reference" technique. SOAP with Attachments is one such example. Since SOAP prohibits document type declarations (DTD) in messages, this leads to the problem of not representing data as part of the message infoset, therefore creating two data models. This scenario is like sending attachments with an e-mail message. Even though those attachments are related to the message content they are not inside the message. This causes the technologies that process and describe the data based on the XML component of the data to malfunction. One example is WS-Security.

Where Does MTOM Come In? MTOM (SOAP Message Transmission Optimization Mechanism) is another specification that focuses on solving the "Attachments" problem. MTOM tries to leverage the advantages of the above two techniques by trying to merge the two techniques. MTOM is actually a "by reference" method. The wire format of a MTOM optimized message is the same as the SOAP with Attachments message, which also makes it backward compatible with SwA endpoints. The most notable feature of MTOM is the use of the XOP:Include element, which is defined in the XML Binary Optimized Packaging (XOP) specification to reference the binary attachments

170

(external unparsed general entities) of the message. With the use of this exclusive element, the attached binary content logically becomes inline (by value) with the SOAP document even though it is actually attached separately. This merges the two realms by making it possible to work only with one data model. This allows the applications to process and describe by only looking at the XML part, making the reliance on DTDs obsolete. On a lighter note, MTOM has standardized the referencing mechanism of SwA. The following is an extract from the XOP specification. At the conceptual level, this binary data can be thought of as being base64-encoded in the XML Document. As this conceptual form might be needed during some processing of the XML document (e.g., for signing the XML document), it is necessary to have a one-to-one correspondence between XML Infosets and XOP Packages. Therefore, the conceptual representation of such binary data is as if it were base64-encoded, using the canonical lexical form of the XML Schema base64Binary datatype (see [XML Schema Part 2: Datatypes Second Edition] 3.2.16 base64Binary). In the reverse direction, XOP is capable of optimizing only base64-encoded Infoset data that is in the canonical lexical form. Apache Axis2 supports Base64 encoding, SOAP with Attachments and MTOM (SOAP Message Transmission Optimization Mechanism).

MTOM with Axis2 Programming Model AXIOM is (and may be the first) Object Model that has the ability to hold binary data. It has this ability as OMText can hold raw binary content in the form of javax.activation.DataHandler. OMText has been chosen for this purpose with two reasons. One is that XOP (MTOM) is capable of optimizing only base64-encoded Infoset data that is in the canonical lexical form of XML Schema base64Binary datatype. Other one is to preserve the infoset in both the sender and receiver. (To store the binary content in the same kind of object regardless of whether it is optimized or not). MTOM allows to selectively encode portions of the message, which allows us to send base64encoded data as well as externally attached raw binary data referenced by the "XOP" element (optimized content) to be sent in a SOAP message. You can specify whether an OMText node that contains raw binary data or base64encoded binary data is qualified to be optimized at the time of construction of that node or later. For optimum efficiency of MTOM, a user is advised to send smaller binary attachments using base64encoding (non-optimized) and larger attachments as optimized content. OMElement imageElement = fac.createOMElement("image", omNs); // Creating the Data Handler for the file. Any implementation of // javax.activation.DataSource interface can fit here. javax.activation.DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("SomeFile")); //create an OMText node with the above DataHandler //and set optimized to true OMText textData = imageElement.addChild(textData); //User can set optimized to false by using the following //textData.doOptimize(false); Also, a user can create an optimizable binary content node using a base64 encoded string, which contains encoded binary content, given with the MIME type of the actual binary representation.

171

String base64String = "some_base64_encoded_string"; OMText binaryNode = Axis2 uses javax.activation.DataHandler to handle the binary data. All the optimized binary content nodes will be serialized as Base64 Strings if "MTOM is not enabled". You can also create binary content nodes, which will not be optimized at any case. They will be serialized and sent as Base64 Strings.

//create an OMText node with the above DataHandler and set "optimized" to false //This data will be send as Base64 encoded string //regardless of MTOM is enabled or not javax.activation.DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("SomeFile")); OMText textData = fac.createOMText(dataHandler, ); image.addChild(textData);

Enabling MTOM Optimization on the Client Side In Options, set the "enableMTOM" property to True when sending messages. ServiceClient serviceClient = new ServiceClient (); Options options = new Options(); options.setTo(targetEPR); serviceClient .setOptions(options); When this property is set to True, any SOAP envelope, regardless of whether it contains optimizable content or not, will be serialized as an MTOM optimized MIME message. Axis2 serializes all binary content nodes as Base64 encoded strings regardless of whether they are qualified to be optimized or not •

if the "enableMTOM" property is set to False.

if the envelope contains any element information items of the name xop:Include (see [XML-binary Optimized Packaging] 3. XOP Infosets Constructs ). •

The user does not have to specify anything in order for Axis2 to receive MTOM optimised messages. Axis2 will automatically identify and de-serialize accordingly, as and when an MTOM message arrives.

Enabling MTOM Optimization on the Server Side The Axis 2 server automatically identifies incoming MTOM optimized messages based on the content-type and de-serializes them accordingly. The user can enableMTOM on the server side for outgoing messages, To enableMTOM globally for all services, users can set the "enableMTOM" parameter to True in the Axis2.xml. When it is set, all outgoing messages will be serialized and sent as MTOM optimized MIME messages. If it is not set, all the binary data in the binary content nodes will be serialized as Base64 encoded strings. This configuration can be overriden in services.xml on the basis of per service and per operation. ●

<parameter name="enableMTOM" locked="false">true

You must restart the server after setting this parameter.

172

Accessing Received Binary Data (Sample Code) Service public class MTOMService { public void uploadFileUsingMTOM(OMElement element) throws Exception { ... ... } }

Client ServiceClient sender = new ServiceClient(); Options options = new Options(); options.setTo(targetEPR); // enabling MTOM ............ OMElement result = sender.sendReceive(payload); OMElement ele = result.getFirstElement(); OMText binaryNode = (OMText) ele.getFirstOMChild(); // Retrieving the DataHandler & then do whatever the processing to the data DataHandler actualDH; actualDH = binaryNode.getDataHandler(); .............

MTOM Databinding You can define a binary element in the schema using the schema type="xsd:base64Binary". Having an element with the type "xsd:base64Binary" is enough for the Axis2 code generators to identify possible MTOM attachments, and to generate code accordingly. Going a little further, you can use the xmime schema (http://www.w3.org/2005/05/xmlmime) to describe the binary content more precisely. With the xmime schema, you can indicate the type of content in the element at runtime using an MTOM attribute extension xmime:contentType. Furthermore, you can identify what type of data might be expected in the element using the xmime:expectedContentType. Putting it all together, our example element becomes: <element name="MyBinaryData" xmime:expectedContentTypes='image/jpeg' > <simpleContent> <extension base="base64Binary" > You can also use the xmime:base64Binary type to express the above mentioned data much clearly.

173

<element name="MyBinaryData" xmime:expectedContentTypes='image/jpeg' type="xmime:base64Binary"/>

MTOM Databinding Using ADB Let's define a full, validated doc/lit style WSDL that uses the xmime schema, has a service that receives a file, and saves it in the server using the given path. <wsdl:definitions xmlns:tns="http://ws.apache.org/axis2/mtomsample/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.apache.org/axis2/mtomsample/"> <wsdl:types> <xsd:schema xmlns="http://schemas.xmlsoap.org/wsdl/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ws.apache.org/axis2/mtomsample/"> <xsd:import namespace="http://www.w3.org/2005/05/xmlmime" schemaLocation="http://www.w3.org/2005/05/xmlmime" /> <xsd:complexType name="AttachmentType"> <xsd:sequence> <xsd:element minOccurs="0" name="fileName" type="xsd:string" /> <xsd:element minOccurs="0" name="binaryData" type="xmime:base64Binary"/> <xsd:element name="AttachmentRequest" type="tns:AttachmentType" /> <xsd:element name="AttachmentResponse" type="xsd:string" />

<wsdl:message name="AttachmentRequest"> <wsdl:part name="part1" element="tns:AttachmentRequest" /> <wsdl:message name="AttachmentResponse"> <wsdl:part name="part1" element="tns:AttachmentResponse" /> <wsdl:portType name="MTOMServicePortType"> <wsdl:operation name="attachment"> <wsdl:input message="tns:AttachmentRequest" wsaw:Action="attachment" /> <wsdl:output message="tns:AttachmentResponse" wsaw:Action="http://schemas.xmlsoap.org/wsdl/MTOMServicePortType/Attachm entResponse"/>

174

<wsdl:binding name="MTOMServiceSOAP11Binding" type="tns:MTOMServicePortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <wsdl:operation name="attachment"> <soap:operation soapAction="attachment" style="document" /> <wsdl:input> <soap:body use="literal" /> <wsdl:output> <soap:body use="literal" /> <wsdl:binding name="MTOMServiceSOAP12Binding" type="tns:MTOMServicePortType"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="attachment"> <soap12:operation soapAction="attachment" style="document" /> <wsdl:input> <soap12:body use="literal" /> <wsdl:output> <soap12:body use="literal" /> <wsdl:service name="MTOMSample"> <wsdl:port name="MTOMSampleSOAP11port_http" binding="tns:MTOMServiceSOAP11Binding"> <soap:address location="http://localhost:8080/axis2/services/MTOMSample"/> <wsdl:port name="MTOMSampleSOAP12port_http" binding="tns:MTOMServiceSOAP12Binding"> <soap12:address location="http://localhost:8080/axis2/services/MTOMSample"/> The important point here is we import http://www.w3.org/2005/05/xmlmime and define the element 'binaryData' that utilizes MTOM. The next step is using the Axis2 tool 'WSDL2Java' to generate Java source files from this WSDL. See the 'Code Generator Tool' guide for more information. Here, we define an Ant task that chooses ADB (Axis2 Data Binding) as the databinding implementation. The name we list for the WSDL above is MTOMSample.wsdl, and we define our package name for our generated source files to 'sample.mtom.service' . Our Ant task for this example is:

175

<java classname="org.apache.axis2.wsdl.WSDL2Java"> <arg value="-uri" /> <arg value="${basedir}/resources/MTOMSample.wsdl" /> <arg value="-ss" /> <arg value="-sd" /> <arg value="-g"/> <arg value="-p" /> <arg value="sample.mtom.service" /> <arg value="-o" /> <arg value="${service.dir}" /> Now we are ready to code. Let's edit output/src/sample/mtom/service/MTOMSampleSkeleton.java and fill in the business logic. Here is an example: public org.apache.ws.axis2.mtomsample.AttachmentResponse attachment( org.apache.ws.axis2.mtomsample.AttachmentRequest param0) throws Exception { AttachmentType attachmentRequest = param0.getAttachmentRequest(); Base64Binary binaryData = attachmentRequest.getBinaryData(); DataHandler dataHandler = binaryData.getBase64Binary(); File file = new File(attachmentRequest.getFileName()); FileOutputStream fileOutputStream = new FileOutputStream(file); dataHandler.writeTo(fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); AttachmentResponse response = new AttachmentResponse(); response.setAttachmentResponse("File saved succesfully."); return response; } The code above receives a file and writes it to the disk using the given file name. It returns a message once it is successful. Now let's define the client:

176

public static void transferFile(File file, String destination) throws RemoteException { MTOMSampleStub serviceStub = new MTOMSampleStub(); // Enable MTOM in the client side serviceStub._getServiceClient().getOptions().setProperty( Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE); //Increase the time out when sending large attachments serviceStub._getServiceClient().getOptions().setTimeOutInMilliSeconds( 10000); // Populating the code generated beans AttachmentRequest attachmentRequest = new AttachmentRequest(); AttachmentType attachmentType = new AttachmentType(); Base64Binary base64Binary = new Base64Binary(); // Creating a javax.activation.FileDataSource from the input file. FileDataSource fileDataSource = new FileDataSource(file); // Create a dataHandler using the fileDataSource. Any implementation of // javax.activation.DataSource interface can fit here. DataHandler dataHandler = new DataHandler(fileDataSource); base64Binary.setBase64Binary(dataHandler); base64Binary.setContentType(dataHandler.getContentType()); attachmentType.setBinaryData(base64Binary); attachmentType.setFileName(destination); attachmentRequest.setAttachmentRequest(attachmentType); AttachmentResponse response = serviceStub.attachment(attachmentRequest); System.out.println(response.getAttachmentResponse()); } The last step is to create an AAR with our Skeleton and the services.xml and then deploy the service. You can find the completed sample in the Axis2 standard binary distribution under the samples/mtom directory

SOAP with Attachments (SwA) with Axis2 Receiving SwA Type Attachments Axis2 automatically identifies SwA messages based on the content type. Axis2 stores the references on the received attachment parts (MIME parts) in the Message Context. Axis2 preserves the order of the received attachments when storing them in the MessageContext. Users can access binary attachments using the attachement API given in the Message Context using the content-id of the mime part as the key. Care needs be taken to rip off the "cid" prefix when content-id is taken from the "Href" attributes. Users can access the message context from whithin a service implementation class using the "setOperationContext()" method as shown in the following example. Note: Axis2 supports content-id based referencing only. Axis2 does not support Content Location based referencing of MIME parts. •

Sample service which accesses a received SwA type attachment

177

public class SwA { public SwA() { } public void uploadAttachment(OMElement omEle) throws AxisFault { OMElement child = (OMElement) omEle.getFirstOMChild(); OMAttribute attr = child.getAttribute(new QName("href")); //Content ID processing String contentID = attr.getAttributeValue(); contentID = contentID.trim(); if (contentID.substring(0, 3).equalsIgnoreCase("cid")) { contentID = contentID.substring(4); } MessageContext msgCtx = MessageContext.getCurrentMessageContext(); Attachments attachment = msgCtx.getAttachmentMap(); DataHandler dataHandler = attachment.getDataHandler(contentID); ........... } }

Sending SwA Type Attachments The user needs to set the "enableSwA" property to True in order to be able to send SwA messages. The Axis2 user is not expected to enable MTOM and SwA together. In such a situation, MTOM will get priority over SwA. This can be set using the axis2.xml as follows. ●

<parameter name="enableSwA" locked="false">true

"enableSwA" can also be set using the client side Options as follows ●

options.setProperty(Constants.Configuration.ENABLE_SwA, Constants.VALUE_TRUE);

Users are expected to use the attachment API provided in the MessageContext to specify the binary attachments needed to be attached to the outgoing message as SwA type attachments. Client side SwA capability can be used only with the OperationClient api, since the user needs the ability to access the MessageContext. •

Sample client which sends a message with SwA type attachments

public void uploadFileUsingSwA(String fileName) throws Exception { Options options = new Options(); options.setTo(targetEPR); options.setProperty(Constants.Configuration.ENABLE_SWA, Constants.VALUE_TRUE); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI ); options.setTo(targetEPR); ServiceClient sender = new ServiceClient(null,null); sender.setOptions(options); OperationClient mepClient = sender.createClient(ServiceClient.ANON_OUT_IN_OP);

178

MessageContext mc = new MessageContext(); mc.setEnvelope(createEnvelope()); FileDataSource fileDataSource = new FileDataSource("testresources/mtom/test.jpg"); DataHandler dataHandler = new DataHandler(fileDataSource); mc.addAttachment("FirstAttachment",dataHandler); mepClient.addMessageContext(mc); mepClient.execute(true); }

MTOM Backward Compatibility with SwA MTOM specification is designed to be backward compatible with the SOAP with Attachments specification. Even though the representation is different, both technologies have the same wire format. We can safely assume that any SOAP with Attachments endpoint can accept MTOM optimized messages and treat them as SOAP with Attachment messages - any MTOM optimized message is a valid SwA message. Note : Above backword compatibility was succesfully tested against Axis 1.x •

A sample SwA message from Axis 1.x

Content-Type: multipart/related; type="text/xml"; start="<9D645C8EBB837CE54ABD027A3659535D>"; boundary="----=_Part_0_1977511.1123163571138" ------=_Part_0_1977511.1123163571138 Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: binary Content-Id: <9D645C8EBB837CE54ABD027A3659535D> <soapenv:Envelope xmlns:soapenv="...."....> ........ <source href="cid:3936AE19FBED55AE4620B81C73BDD76E" xmlns="/> ........ ------=_Part_0_1977511.1123163571138 Content-Type: text/plain Content-Transfer-Encoding: binary Content-Id: <3936AE19FBED55AE4620B81C73BDD76E> Binary Data..... ------=_Part_0_1977511.1123163571138-•

Corresponding MTOM message from Axis2

179

Content-Type: multipart/related; boundary=MIMEBoundary4A7AE55984E7438034; type="application/xop+xml"; start="<[email protected]>"; start-info="text/xml; charset=utf-8" --MIMEBoundary4A7AE55984E7438034 content-type: application/xop+xml; charset=utf-8; type="application/soap+xml;" content-transfer-encoding: binary content-id: <[email protected]> <soapenv:Envelope xmlns:soapenv="...."....> ........ <xop:Include href="cid:[email protected]" xmlns:xop="http://www.w3.org/2004/08/xop/include"> ........ --MIMEBoundary4A7AE55984E7438034 content-type: application/octet-stream content-transfer-encoding: binary content-id: <[email protected]> Binary Data..... --MIMEBoundary4A7AE55984E7438034--

Advanced Topics File Caching for Attachments Axis2 comes handy with a file caching mechanism for incoming attachments, which gives Axis2 the ability to handle very large attachments without buffering them in the memory at any time. Axis2 file caching streams the incoming MIME parts directly into the files, after reading the MIME part headers. Also, a user can specify a size threshold for the File caching (in bytes). When this threshold value is specified, only the attachments whose size is bigger than the threshold value will get cached in the files. Smaller attachments will remain in the memory. Note : It is a must to specify a directory to temporarily store the attachments. Also care should be taken to clean that directory from time to time. The following parameters need to be set in Axis2.xml in order to enable file caching. <parameter name="cacheAttachments" locked="false">true <parameter name="attachmentDIR" locked="false">temp directory <parameter name="sizeThreshold" locked="false">4000 ......... .........

180

Enabling file caching for client side receiving can be done for the by setting the Options as follows.

options.setProperty(Constants.Configuration.CACHE_ATTACHMENTS,Constants. VALUE_TRUE); options.setProperty(Constants.Configuration.ATTACHMENT_TEMP_DIR,TempDir) ; options.setProperty(Constants.Configuration.FILE_SIZE_THRESHOLD, "4000");

Transports HTTP Transport This document is all about HTTP sender and HTTP receiver, and how they work in Axis2. Send your feedback or questions to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

Content •

CommonsHTTPTransportSender •

HTTPS support



Timeout Configuration



HTTP Version Configuration



Proxy Authentication



Basic,Digest and NTLM Authentication

CommonsHTTPTransportSender This is the default transport sender that is used in Server API as well as Client API. As the name implies, it is based on commons-httpclient-3.0.1. In order to acquire the maximum flexibility, this sender has implemented POST interface and GET interface. GET and HTTP interfaces are also involved in Axis2 REST support. Chunking and KeepAlive support is also integrated via the facilities provided by commonshttpclient along with HTTP 1.1 support. element is used to define transport senders in the axis2.xml as follows: <parameter name="PROTOCOL" locked="false">HTTP/1.1 <parameter name="Transfer-Encoding">chunked The above code snippet shows the simplest configuration of a transport sender for common use. <parameter/> element introduces the additional parameters that should be compliant with the sender. HTTP PROTOCOL version sets as HTTP/1.0 or HTTP/1.1. The default version is HTTP/1.1. It should be noted that chunking support is available only for HTTP/1.1. Thus, even if the user turns on "chunking", if the HTTP version is 1.0, this setting will be ignored by the transport framework. KeepAlive is a default property in version 1.1.

181

Some absolute properties are provided at runtime, such as character encoding style (UTF-8, UTF-16 etc) is provided via MessageContext.

HTTPS support It should be noted that CommonsHTTPTransportSender can be used to communicate over https. <parameter name="PROTOCOL" locked="false">HTTP/1.1 <parameter name="Transfer-Encoding">chunked Please note that HTTPS works only when the server does not expect to authenticate the clients and where the server has the clients' public keys in its trust store.

Timeout Configuration Two timeout instances exist in the transport level. They are called, Socket timeout and Connection timeout. This can be configured at deployment time or run time. At the time of deployment, the user has to add the following lines in axis2.xml. For Socket timeout: <parameter name="SO_TIMEOUT" locked="false">some_int_value For Connection timeout: <parameter name="CONNECTION_TIMEOUT" locked="false">some_int_value At runtime, it is set as follows in the Stub.

... Options options = new Options(); options.setProperty(HTTPConstants.SO_TIMEOUT,new Integer(timeOutInMilliSeconds)); options.setProperty(HTTPConstants.CONNECTION_TIMEOUT,new Integer(timeOutInMilliSeconds)); // or options.setTimeOutInMilliSeconds(timeOutInMilliSeconds); ...

HTTP Version Configuration The default HTTP version is 1.1. There are two methods in which the user can change the HTTP version to 1.0 1. By defining the version in axis2.xml as shown below. <parameter name="PROTOCOL" locked="false">HTTP/1.0 2. Or the user can change the version at runtime by doing the following ... options.setProperty(org.apache.axis2.context.MessageContextConstants.HTTP_ PROTOCOL_VERSION,org.apache.axis2.transport.http.HTTPConstants.HEADER_PROT OCOL_10); ...

182

Proxy Authentication The Commons-http client has the inbuilt ability to support proxy authentication. Axis2 uses deployment time and runtime mechanisms to authenticate proxies. At deployment time, the user has to change the axis2.xml as follows. This authentication will be available in HTTP and HTTPS. <parameter name="PROTOCOL" locked="false">HTTP/1.1 <parameter name="PROXY" proxy_host="proxy_host_name" proxy_port="proxy_host_port" locked="true>userName:domain:passWord For a particular proxy, if authentication is not available, "userName:domain:passWord"as "anonymous:anonymous:anonymous".

enter

thel

At runtime, the user can override the PROXY settings with an Object of HttpTransportProperties.ProxyProperties. On the stub, initiate an object of the prior setting and set it to the MessageContext's property bag via HttpConstants.PROXY. On the stub, it depicts as follows, ... Options options = new Options(); .... HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.new ProxyProperties(); proxyProperties.setProxyHostName(....); proxyProperties.setProxyPort(...); ... options.setProperty(HttpConstants.PROXY, proxyProperties); ....

The above code would eventually override the deployment proxy configuration settings.

Basic, Digest and NTLM Authentication HttpClient supports three different types of HTTP authentication schemes: Basic, Digest and NTLM. Based on the challenge provided by the server, httpclient automatically selects the authentication scheme with which the request should be authenticated.. The most secure will be NTLM and the least secure will be Basic. NTLM is the most complex of the authentication protocols supported by HttpClient. It requires an instance of NTCredentials to be available for the domain name of the server or the default credentials. Note that since NTLM does not use the notion of realms, HttpClient uses the domain name of the server as the name of the realm. Also note that the username provided to the NTCredentials should not be prefixed with the domain - ie: "axis2" is correct whereas "DOMAIN\axis2" is not correct. There are some significant differences in the way that NTLM works compared with basic and digest authentication. These differences are generally handled by HttpClient, however having an understanding of these differences can help avoid problems when using NTLM authentication. 1. NTLM authentication works almost exactly the same way as any other form of authentication in terms of the HttpClient API. The only difference is that you need to

183

supply 'NTCredentials' instead of 'UsernamePasswordCredentials' (NTCredentials actually extends UsernamePasswordCredentials so you can use NTCredentials right throughout your application if need be). 2. The realm for NTLM authentication is the domain name of the computer to which you are being connected. This can be troublesome as servers often have multiple domain names that refer to them. Only the domain name that the HttpClient connects to (as specified by the HostConfiguration) is used to look up the credentials. It is generally advised that while initially testing NTLM authentication, you pass the realm as null, which is used by default. 3. NTLM authenticates a connection and not a request. So you need to authenticate every time a new connection is made, and keeping the connection open during authentication is vital. Due to this, NTLM cannot be used to authenticate with both a proxy and the server, nor can NTLM be used with HTTP 1.0 connections or servers that do not support HTTP keep-alives. Axis2 also allows to add a custom Authentication Scheme to httpclient. The static inner bean Authenticator of HttpTransportProperties will hold the state of the server to be authenticated with. Once filled, it has to be set to the Options's property bag with the key as HTTPConstants.AUTHENTICATE. The following code snippet shows the way of configuring the transport framework to use Basic Authentication:

... Options options = new Options(); HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator(); auth.setUsername("username"); auth.setPassword("password"); // set if realm or domain is know options.setProperty(org.apache.axis2.transport.http.HTTPConstants.BASIC _AUTHENTICATE,auth); ...

JMS Transport This document is all about the JMS (Java Messaging Service) Transport support in Apache Axis2,, and how it should be configured. Send your feedback or questions to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

Contents •

Overview



Configuration



Writing Services to Use the JMS Transport

Overview A new Java Messaging Service (JMS) transport implementation has been added to Axis2 to overcome some drawbacks of the previous JMS implementation. One of the enhancements provided with this new implementation is the ability to assign custom JMS destination names or existing JMS destinations to Axis2 services being deployed.

184

Configuration To use the JMS transport, the axis2.xml configuration must be setup as follows, in order to configure the JMSListener and the JMS Sender <parameter name="default" locked="false"> <parameter name="java.naming.factory.initial" locked="false"> org.apache.activemq.jndi.ActiveMQInitialContextFactory <parameter name="java.naming.provider.url" locked="false"> tcp://localhost:61616 <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false"> QueueConnectionFactory The JMS transport receiver configuration allows you to define the default connection factory (named as "default" ~ JMSConstants.DEFAULT_CONFAC_NAME) for use by Axis2 services using the JMS transport. This connection factory will be used by any service that does not explicitly specify a connection factory name in its services.xml file. The configuration required to associate a (local) Axis2 connection factory to an actual implementation must be provided as shown above. To specify the JNDI URL, the initial context factory class and the JNDI name of the actual JMS connection factory is used. You can also specify the parameters "java.naming.security.principal" and "java.naming.security.credentials", if required, to access the actual connection factory. The example shown above uses an ActiveMQ JMS implementation. <parameter name="myTopicConnectionFactory" locked="false"> <parameter name="java.naming.factory.initial" locked="false"> org.apache.activemq.jndi.ActiveMQInitialContextFactory <parameter name="java.naming.provider.url" locked="false"> tcp://localhost:61616 <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false"> TopicConnectionFactory If it is required or applicable, you are free to define additional (local) connection factories to Axis2 as shown above, which your services can use. For a service to specify that such a connection factory should be used, its services.xml may specify the following configuration parameter: services.xml <parameter name="transport.jms.ConnectionFactory" locked="true">myTopicConnectionFactory

185

Note: Depending on your JMS implementation, you will need to make available all the required libraries for your Axis2 instance. This example assumes you are using an ActiveMQ instance. To run the given code samples, it is required to make the following JAR files available: activeio-core-3.0-beta1.jar, activemq-core-4.0-RC2.jar, geronimo-j2eemanagement_1.0_spec-1.0.jar at a minimum. It also requires you to start ActiveMQ separately from Axis2, and then provide the appropriate configuration settings (e.g. URL) to Axis2. During initialization, the JMS Listener creates a dedicated JMS message processor for each connection factory defined, and utilizes a shared thread pool to process the received messages. A service on an Axis2 instance is deployed on all the started transports by default, unless a list of transports is specified in its services.xml file. Hence, if a service must only be deployed on JMS, you should specify it on the services.xml as follows: jms If the services.xml does not provide an explicit JMS destination name, it is assumed that the service will listen for messages on a JMS Queue by the same name as the name of the service. If an explicit connection factory definition name has not been specified, it is assumed that the "default" connection factory definition configured within the transport receiver is used. To provide a custom JMS destination name and connection factory, the services.xml file provides the following optional parameters.

<parameter name="transport.jms.ConnectionFactory" locked="true">myTopicConnectionFactory <parameter name="transport.jms.Destination" locked="true">dynamicTopics/something.TestTopic

Writing Services to Use the JMS Transport This section assumes that you are already familiar with writing service implementations for Axis2, and provides information on how to write your own service implementations, which are exposed over JMS.

Echo - Service implementation and services.xml This sample demonstrates a very simple service which is to be exposed over JMS. It does not specify a custom connection factory name, and hence uses the default value as specified in the JMS transport listener configuration. It also does not specify a custom destination name, and hence would listen to messages over a JMS Queue named "Echo" (which is the name of the service). This service will be exposed over all defined Axis2 transports, and the resulting URL for the service over JMS will be: jms:/echo?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.nami ng.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provid er.url=tcp://localhost:61616

186

public class Echo { public String echoString(String in) { return in; } public String echoString1(String in) { return "echoString1 " + in; } public String echoString2(String in) { return "echoString2 " + in; } } <service name="echo"> <description>Echo Service <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass" locked="true">Echo

Echo2 - Service implementation and services.xml This example shows a simple service which specifies that it should only be exposed over the JMS transport, and that the custom connection factory named "myTopcConnectionFactory" should be used to listen for requests at the JMS destination named "dynamicTopics/something.TestTopic". The JMS URL to access this service is: jms:/dynamicTopics/something.TestTopic?transport.jms.ConnectionFactoryJNDIName=Topic ConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContex tFactory&java.naming.provider.url=tcp://localhost:61616&java.naming.security.principal=syste m&java.naming.security.credentials=manager public class Echo2 { public String echoString(String in) { return in; } }

<service name="echo"> jms <description>Echo2 Service <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> <parameter name="ServiceClass" locked="true">Echo2 <parameter name="transport.jms.ConnectionFactory" locked="true">myTopicConnectionFactory <parameter name="transport.jms.Destination" locked="true">dynamicTopics/something.TestTopic

187

Starting up the Axis2 JMS transport The Axis2 standalone binary distribution ships with an Axis2 Server, which starts up all the transports that are configured as per the axis2.xml. Hence, configure the JMS transport in your axis2.xml, and use the axis2server.bat or the axis2server.sh to start the JMS transport.

TCP Transport This document explains how to send and receive SOAP messages via TCP in Axis2. Send your feedback or questions to: [email protected]. Prefix subject with [Axis2]. Subscription details are available on the Axis2 site.

Content •

Introduction



How to Start the TCPServer



How to Send SOAP Messages Using TCP Transport



Samples



Transport Components

Introduction Axis2 supports TCP as a transport. It supports both sending and receiving SOAP messages via TCP. A TCP transport does not have any application level headers and the SOAP message that is sent should be self-contained. This makes the interaction fast and simple. However, since there are no application headers, it does not have the privilege of having a request URI, and Service dispatching should be done by an alternative method. Thus, RequestURIBasedDispatcher cannot be used. The following are the two main alternatives available for dispatching in the Axis2 environment: 1. Use the name space URI of (SOAPMessageBodyBasedDispatcher).

the

first

child

element

of

SOAPBody.

2. Enable WS-Addressing. In the case of version 1.1 and 1.1.1 releases Addressing is default (SOAPActionBasedDispatcher). When the TCP request is sent, it is the user's responsibility to use either Addressing or the SOAP body base mechanism.

How to Start the TCPServer The TCP server can be started by running the class org.apache.axis2.transport.tcp.TCPServer with two parameters - repository and port number, as arguments. This class needs all the Axis dependency JARs in the classpath. New services can be added in the usual way by dropping the archives to the repository (See Advanced User's Guide for more information)

How to Send SOAP Messages Using TCP Transport TCP transport can be enabled easily from the call API. The following code segment demonstrates how this can be done.

188

OMElement payload = ... ServiceClient serviceClient = new ServiceClient(); Options options = new Options(); options.setTo(targetEPR); serviceClient.setOptions(options); OMElement response = serviceClient.sendReceive(payload); The transport that should be invoked is inferred from the targetEPR (tcp://...). In this case it is TCP and the listener is also TCP. The SOAP message has to be self contained in order to use Addressing. The other option is to use the URI of the first child of the SOAP Body to dispatch the service. The parameter is of the type OMElement, the XML representation of Axis2.

Samples A sample for a TCP Client can be found from the samples/userguide/src/userguide/clients/TCPClient.java in the binary distribution. This accesses the same Web service explained in the Axis2 Advanced User's Guide. The client first starts the TCPServer with the same repository used for the Axis2 Advanced User's Guide samples. Since the sample is already deployed in the repository, as per the userguide, it will be automatically available. In order to run the TCPClient.java, addressing should be engaged both in the client and server sides. On the client side, you can engage addressing by copying the addressing-1.2.mar (AXIS2_HOME/repository/module) to AXIS2_HOME/lib directory.

Transport Components The Axis2 TCP transport has two components, a transport Listener for receiving the messages and a transport Sender to send the SOAP Messages. The Axis2 installation has both the components built into itself by default. In the axis2.xml configuration file, the two TCP transport components can be configured as shown below. The following XML lines initialize the TCPTransport Receiver: <parameter name="port" locked="false">6060 The following XML lines add the TCPTransport Sender: Note: If the TCP server is started manually, this configuration does not take effect. In return, this affects the transport Listener's start by Axis2. (e.g. Listener started by the Complete Async interaction)

Mail Transport Invoking a Service Using a Mail Transport This document explains how to invoke a service through Mail transports.

189

Send your feedback or questions to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

Content •

Prologue



Introduction



Using Simple Mail Server Included in Axis2



Using a Generic Mail Server

Prologue Most of the Web services that we interact with are synchronous and request-response in nature. However, we see that the synchronous request-response type of interaction is only a part of the messaging scenarios we encounter in real life. Asynchronous messaging is very important in constructing loosely coupled systems. Take for instance a chain of stores. At the end of the day, all the stores can send a mail to the central system telling it about that day's business activities, and when the store opens in the morning, there will be a reply to that mail with new instructions and updates. It is a lot like the way old businesses worked, but with a modern touch. Similarly, the Axis2 mail transport can be used to implement asynchronous messaging through mail.

Introduction First, you need to go through the Mail Transport Configuration document. It provides first hand experience in setting up the mail transports to operate with Axis2. Broadly speaking, there are three ways of calling a service through mail. 1. Using the simple mail server included in Axis2 (not recommended in production). 2. Using a generic mail server. 3. Using mailets. Options 1 and 2 are fairly simple and easy to implement, whereas option 3 is somewhat harder. The mailet scenario however does provide a more robust and useful solution in a production environment. It is very easy to start learning the workings of mail transports with the aid of the Simple Mail Server that is provided with Axis2. Once you get the hang of Axis2 related issues, then you can move on to tackle the mail beast. Please do note that the Simple Mail Server provided with Axis2 is not graded for production use.

1. Using the Simple Mail Server Included in Axis2 The SMTP/POP server that we have included has the ability to function as a standalone SMTP/POP server and also has the ability to work as a mailet. All this is done through a small filter that keeps watch for certain pre-configured email addresses. These pre-configured email addresses can be changed by doing a simple edit of the filter class org.apache.axis2.transport.mail.server.Sorter. Now that we have the environment set up, we can use the code below to get the mail functionality started. First we'll have a look at it from the mail server side.

190

// Start the mail server using the default configurations. ConfigurationContext configContext = UtilsMailServer.start(); // Start the default mail listener. It will starting polling for mail // using the configuration from the XML file. SimpleMailListener ml = new SimpleMailListener(); ml.init(configContext, configContext.getAxisConfiguration().getTransportIn(new QName(Constants.TRANSPORT_MAIL))); ml.start(); private QName serviceName = new QName("EchoXMLService"); private QName operationName = new QName("echoOMElement"); // Setup a service that will echo what we send to the server. AxisService service = Utils.createSimpleService(serviceName, Echo.class.getName(), operationName); serverConfigContext.getAxisConfiguration().addService(service); This code sets up your Axis2 server which uses a single service to work through the mail. If you want to have a look under the hood, check out the MailServer and UtilsMailServer classes. Moving onto the client side, have a look at the code listing below. It will call the axisService that was setup in the previous code listing. ConfigurationContext configContext = UtilsMailServer.createClientConfigurationContext(); AxisService service = new AxisService(serviceName.getLocalPart()); AxisOperation axisOperation = new OutInAxisOperation(); axisOperation.setName(operationName); axisOperation.setMessageReceiver(new MessageReceiver() { public void receive(MessageContext messageCtx) { envelope = messageCtx.getEnvelope(); } Callback callback = new Callback() { }); public void onComplete(AsyncResult result) { service.addOperation(axisOperation); try { configContext.getAxisConfiguration().addService(service); result.getResponseEnvelope().serializeAndConsume(XMLOutputFactory. ServiceContext serviceContext = new ServiceGroupContext(configContext, newInstance().createXMLStreamWriter(System.out)); (AxisServiceGroup) service.getParent()).getServiceContext(service); } catch (XMLStreamException e) { onError(e); Options options = new Options(); } finally { options.setTo(targetEPR); finish = true; options.setAction(operationName.getLocalPart()); } options.setTransportInProtocol(Constants.TRANSPORT_MAIL); } options.setUseSeparateListener(true); public void onError(Exception e) { log.info(e.getMessage()); finish = true; } }; ServiceClient sender = new ServiceClient(configContext, service); sender.setOptions(options); //options.setTo(targetEPR); sender.sendReceiveNonBlocking(operationName,createEnvelope(), callback); int index = 0; while (!finish) { Thread.sleep(1000); index++; if (index > 10) { throw new AxisFault("Server was 191 shutdown as the async response is taking too long to complete."); } } }

This will call the service that was setup on the server, and will poll the mail server until the response is received. Please note that the serviceName and operationName need to be QNames.

2. Using a Generic Mail Server First you will need two email accounts that work with POP/SMTP. One will act as a server and the other will act as the client. For the time being, we will use [email protected] and [email protected] as the server and the client email addresses. Now that we have the email addresses, you will have to set up the client and the server using the Mail Transport configuration document. When you call the generic mail server, the client side code will remain the same and there will be some modification to the server-side code. // Create a configuration context. This will also load the details // about the mail address to listen to from the configuration file. File file = new File(MAIL_TRANSPORT_SERVER_ENABLED_REPO_PATH); ConfigurationContextFactory builder = new ConfigurationContextFactory(); ConfigurationContext configContext = configContextbuilder.buildConfigurationContext(file.getAbsolutePath());

// Start the default mail listener. It will starting poling for mail // using the configuration from the XML file. SimpleMailListener ml = new SimpleMailListener(); ml.init(configContext, configContext.getAxisConfiguration().getTransportIn(new QName(Constants.TRANSPORT_MAIL))); ml.start(); private QName serviceName = new QName("EchoXMLService"); private QName operationName = new QName("echoOMElement"); // Setup a service that will echo what we send to the server. AxisService service = Utils.createSimpleService(serviceName, Echo.class.getName(), operationName); serverConfigContext.getAxisConfiguration().addService(service); Note that a separate ConfigurationContext needs to be created and used.

Resources For more information on Mail client AXIS2_HOME\samples\userguide\src\userguide\clients\MailClient.java

invocation,

see

Mail Transport Configuration This document provides guidelines on how to configure Axis2 in order to get the mail transport working. Send your feedback or questions to: [email protected]. (Subscription details are available on the Axis2 site.) Kindly prefix subject with [Axis2].

192

Content •

Introduction



Transport Sender



Transport Receiver



Using Mail Transport in the Server Side



Configure James as SMTP and POP Server



Using the Included Mail Server

Introduction The inner workings of the mail transport has been divided into two parts: the transport sender for SMTP and the transport listener for POP3. The transport listener will listen to a particular email address periodically. When an email comes in, it will be tunneled into an Axis2 engine. On the other hand, the mail transport sender sends emails to a mail server to a particular email address. Mail transport can be used against a generic mail server or it can be used like a mailet. The simple mailet provided with Axis2 directs any message that comes in to a particular address into the Axis engine. The engine will process the message and use the Transport sender to send the reply. The mail transports have been written with the use of Sun's JavaMail and Activation jars. They should be available in your classpath to get the mail transport to work.

Transport Sender You need to have a mail account to activate the mail functionality. This can either be a generic mail server or you can start up a James mail server. JavaMail sets its properties to a Properties object. In Axis2, this has been mapped to a Parameter object. Mapping has been done as follows, Every JavaMail property can be set to @name of the <parameter/>. Thus, an SSL connection is mapped the way it is done in JavaMail • •

Few properties, such as password,, are set to @name with the prefix "transport"

For a non-SSL connection, as an example, the mail transport sender can be activated by adding the following entry to the axis2.xml file. <parameter name="mail.smtp.host" locked="false">localhost <parameter name="mail.smtp.user" locked="false">mary <parameter name="transport.mail.smtp.password" locked="false">mary At runtime, tuning a client to set the mail transport is as easy as follows,

193

... Options options = new Options(); HttpTransportProperties.MailProperties mailProps = new HttpTransportProperties.MailProperties(); mailProps.addProperty("mail.smtp.host","localhost"); mailProps.addProperty("mail.smtp.user","mary"); mailProps.setPassword("mary"); options.setProperty(HTTPConstants.MAIL_SMTP,mailProps); ... Thus, a user who is familiar with setting up an SSL connection, should easily do it with the MailProperties object. For example, tuning the sender to talk to the gmail account. This configuration should also be done with <parameter/> in axis2.xml. HttpTransportProperties.MailProperties props = new HttpTransportProperties.MailProperties(); props.put("mail.smtp.user", "[email protected]"); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.port", "465"); props.put("mail.smtp.starttls.enable","true"); props.put("mail.smtp.auth", "true"); //props.put("mail.smtp.debug", "true"); // if the user wants props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); props.setPassword("password");

Transport Receiver For a non-SSL connection, as an example, the mail Listener can be activated by adding the following entry to the axis2.xml file. <parameter name="mail.pop3.host" locked="false">localhost <parameter name="mail.pop3.user" locked="false">bob <parameter name="transport.mail.pop3.password" locked="false">bob <parameter name="transport.mail.replyToAddress" locked="false">bob@localhost Note: The @name="transport.mail.replyToAddress" is an important parameter. It supplies the Endpoint reference to the listener. For an advanced user, this can be set to an SSL connection. For example, let's use this transport listener to pop from a specified gmail account.

194

<parameter name="mail.pop3.host" locked="false">pop.gmail.com <parameter name="mail.pop3.user" locked="false">[email protected] <parameter name="mail.pop3.socketFactory.class" locked="false">javax.net.ssl.SSLSocketFactory <parameter name="mail.pop3.socketFactory.fallback" locked="false">false <parameter name="mail.pop3.port" locked="false">995 <parameter name="mail.pop3.socketFactory.port" locked="false">995 <parameter name="transport.mail.pop3.password" locked="false">password <parameter name="transport.mail.replyToAddress" locked="false">[email protected]

Using Mail Transport in the Server Side If the Mail Listener is to be started as a standalone mail listener, it can be done with the following command with the all the Axis2 jars and the mail dependency jars in the classpath. java org.apache.axis2.transport.mail.SimpleMailListener repository-directory

Using Mail Transport in the Client Side The following code segment shows how to send a one-way (IN-Only MEP) SOAP message using the mail transport. This needs the Transport Sender to be configured.

OMElement payload = .... String targetEPR = "mail:axis2@localhost/axis2/services/Foo"; ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(rep o, axis2XML); ServiceClient servicClient = new ServiceClient(configurationContext, null); Options options = new Options(); options.setTo(targetEPR); options.setTransportInProtocol(Constants.TRANSPORT_MAIL); servicClient.setOptions(options); servicClient.sendRobust(payload);

Configure James as SMTP and POP Server Download Apache James and start James. Connect to the James server via Telnet as administrator James using the following code:

195

$telnet 127.0.0.1 4555 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. JAMES Remote Administration Tool 2.2.0 Please enter your login and password Login id: root Password: root Welcome root. HELP for a list of commands Add users to James adduser axis2-server axis2 User axis2-server added adduser axis2-client axis2 User axis2-client added Connection closed by foreign host. Now James is up and running with the accounts.

Using the Included Mail Server The inbuilt mail server can be started from the command line using the following command when all the necessary JARS are in the class path. java org.apache.axis2.transport.mail.server.MailServer The server itself does not need any configuration or tinkering to work. A ConfigurationContext and the ports to operate on are the only details needed. The server will store the mails in the memory against the recipient till the recipient pops it from the server. To facilitate the use in Linux environments as a non root user, the POP and SMTP ports used by default configuration/test cases are, 1024, 25 and 1024, 110 respectively.

How to Write Your Own Axis2 Transport Prologue To stop you from re-inventing the wheel, before we get started, I will quickly list the transports that are already supported in Axis2 with a small description. HTTP - In the HTTP transport, the transport Listener is either a Servlet or a Simple HTTP server provided by Axis2. The transport Sender uses sockets to connect and send the SOAP message. Currently we have the commons-httpclient based HTTP Transport sender as the default transport. •

TCP - This is the most simple transport, but needs Addressing support to be functional. •

SMTP - This can work off a single email account or a mail server. The Mail Transport Receiver is a thread that checks for emails in fixed time intervals. •

To understand the rest of this document you will need some understanding of the architecture of Axis2. If you are not familiar with the Axis2 architecture, please go through the Axis2 Architecture Guide before you read any further.

196

Introduction Broadly speaking, a transport inside Axis2 can be classified as a way of getting messages that arrive though some channel into the Axis2 engine. The core of Axis2 is transport independent. All data that is transport specific is stripped out of the incoming message and inserted into the MessageContext. In the outgoing message, all transport specific information, like headers, are added and sent. To write your own transport, you will primarily need to write two classes: one is the TransportSender and the other is the TransportReceiver. To register a transport with Axis2 you will need to put entries corresponding to these two classes in the axis2.xml file. I will take you through the process of adding the entries in the relevant sections.

Transport Receiver Any message that is coming into Axis2 needs to go through a transport receiver. All information about how the message is received at the Axis2 server from the wire (or via an email) is isolated inside the transport receiver. It extracts the data that is coming on the wire and transforms it into a state that the Axis2 server understands. So now that we have some background information about how transports work inside Axis2, without further delay, lets dive into some coding and start building our own transport. To get things stared, you will first need to extend from the org.apache.Axis2.transport.TransportListener class and write your own transport listener. To create an engine to process the MessageContext, we need a configuration context. The following code fragment will do this. This should ideally be only done once for the lifetime of the Transport receiver.

try { //Create a factory ConfigurationContextFactory factory = new ConfigurationContextFactory(); //Use factory and Axis2 repository to create a new Configuration Context configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(rep ository_directory, axis2xmllocation); } catch (Exception e) { log.info(e.getMessage()); } Now we need some kind of a Listener to listen to the requests that come in. You need to implement this according to the transport that you are trying to build. After a message is received at the Receiver, you can use the following code to process the request and then forward the message context to the engine using the engine.receive(msgContext) method. (The following code is extracted from the MailListener as an example)

197

AxisEngine engine = new AxisEngine(configurationContext); MessageContext msgContext = null; // create and initialize a message context try { TransportInDescription transportIn = reg.getAxisConfiguration().getTransportIn(new QName(Constants.TRANSPORT_NAME)); TransportOutDescription transportOut = reg.getAxisConfiguration().getTransportOut(new QName(Constants.TRANSPORT_NAME)); if (transportIn != null && transportOut != null) { //create Message Context msgContext = new MessageContext(configurationContext, transportIn, transportOut); msgContext.setServerSide(true); msgContext.setProperty(MailSrvConstants.CONTENT_TYPE, message.getContentType()); msgContext.setProperty(MessageContext.CHARACTER_SET_ENCODING, message.getEncoding()); String soapAction = message.getSOAPActionHeader(); msgContext.setWSAAction(soapAction); msgContext.setSoapAction(soapAction); // Here we are trying to set the reply to if it is present in the //transport information. msgContext.setReplyTo(new EndpointReference(message.getReplyTo()); String soapNamespaceURI = ""; if(message.getContentType().indexOf(SOAP12Constants.SOAP_12_CONTENT_TY //Create the SOAP Message -- This code in from the mail transport and PE) > -1){ //will change depending on how the data is handled in each transport. soapNamespaceURI = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI; ByteArrayInputStream bais = new } ByteArrayInputStream(message.getContent().toString().getBytes()); else XMLStreamReader reader = if(message.getContentType().indexOf(SOAP11Constants.SOAP_11_CONTENT_ XMLInputFactory.newInstance().createXMLStreamReader(bais); TYPE) > -1){ soapNamespaceURI = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI; } StAXBuilder builder = new StAXSOAPModelBuilder(reader, soapNamespaceURI); SOAPEnvelope envelope = (SOAPEnvelope) builder.getDocumentElement(); msgContext.setEnvelope(envelope); if (envelope.getBody().hasFault()) { engine.receiveFault(msgContext); } else { engine.receive(msgContext); } } else { throw new AxisFault(Messages.getMessage("unknownTransport",Constants.TRANSPORT_NAM E)); } } catch (Exception e) { try { if (msgContext != null) { MessageContext faultContext = engine.createFaultMessageContext(msgContext, e); engine.sendFault(faultContext); } else { log.error(e); 198 } } catch (AxisFault e1) { log.error(e); } }

Now that we have the coding in place, we need to let Axis2 know about our new transport receiver. We do this by adding an entry into the axis2.xml file. If you need to pass any properties for the transport to operate, it can also be done through the axis2.xml file. <parameter name="PROPERTY_NAME" locked="false">PROPERTY_VALUE <parameter name="PROPERTY_NAME_2" locked="false">PROPERTY_VALUE_2 By using a code fragment like Utils.getParameterValue(transportOut.getParameter(MailSrvConstants.SMTP_USER)) we can extract the parameters that we inserted into the axis2.xml file. As you can see, getting a new transport receiver up and running is a task that requires very little effort.

Transport Sender Any message that is to be sent out of Axis2, is sent through the Transport Sender. The Transport Sender needs to be extended from the org.apache.Axis2.transport.AbstractTransportSender class. The following bit of code from the abstract transport sender will call the Transport Sender that you wrote.

199

// If an EPR is present then the message is going on a different channel. if (epr != null) { out = openTheConnection(epr, msgContext); OutputStream newOut = startSendWithToAddress(msgContext, out); if (newOut != null) { out = newOut; } writeMessage(msgContext, out); finalizeSendWithToAddress(msgContext, out); } else { out = (OutputStream) msgContext.getProperty(MessageContext.TRANSPORT_OUT); if (out != null) { startSendWithOutputStreamFromIncomingConnection(msgConte xt, out); writeMessage(msgContext, out); finalizeSendWithOutputStreamFromIncomingConnection(msgCo ntext, out); } else { throw new AxisFault( "Both the TO and Property MessageContext.TRANSPORT_WRITER is Null, No way to send response."); } } Therefore, depending on whether your transport is using the same channel to send the response or using a different channel, you will need to implement a sub-set of the methods from the abstract class. After implementing the necessary methods, you can let Axis2 know about your new transport sender by adding an entry to the axis2.xml file, like you did for the transport receiver. <parameter name="PROPERTY_NAME" locked="false">PROPERTY_VALUE <parameter name="PROPERTY_NAME_2" locked="false">PROPERTY_VALUE_2 Have a look at org.apache.Axis2.transport.mail.MailTransportSender for a very simple Transport Sender. Also have a look at org.apache.Axis2.transport.http.CommonsHTTPTransportSender which is used to send HTTP responses. Once we have written our transport receiver and our transport sender, and inserted the required entries into the axis2.xml file, we are done. It is as simple as that!

200

Related Documents


More Documents from ""