Axis C++ User Guide

Contents

Introduction
What's in this release
Axis C++ now delivers the following key features
What's Missing
Installing Axis and Using this Guide
Download Source Distribution
ServerSide Skeleton and Wrappers generated by WSDL2ws Tool.
Deploying Services
Client side Stubs Generated by the wsdl2ws Tool
Handler Sample
Download Binary
ServerSide Skeleton and Wrappers generated by WSDL2ws Tool.
Deploying Services
Client side Stubs Generated by the wsdl2ws Tool
Handler Sample
Getting a CVS checkout

Introduction

Welcome to Axis C++, the opensource c++ implementation of SOAP ! What is SOAP? SOAP is an XML-based communication protocol and encoding format for inter-application communication. Originally conceived by Microsoft and Userland software, it has evolved through several generations and the current spec, SOAP 1.2 is fast growing in popularity and usage. The W3C's XML Protocol working group is in the process of turning SOAP into a true open standard, and as of this writing has released a working draft of SOAP 1.2, which cleans up some of the more confusing areas of the 1.1 spec. SOAP is widely viewed as the backbone to a new generation of cross-platform cross-language distributed computing applications, termed Web Services. What is Axis C++? Axis C++ is essentially a SOAP engine.

This version is written in C++. Axis C++ SOAP engine adopts most of Axis Java architecture. But it has some major architectural innovations over Axis Java in order to achieve greater performance and efficiency.

What's in this release?

- Soap engine with both client and server support

- Partial support for both SOAP 1.1 and SOAP 1.2

- WSDD based deployment with dynamic deployment tools.

- Support for all basic types, Complex types and Arrays

- WSDL2WS tool for building C/C++ components

- Server side – Skeletons and Wrappers

- Client side – Stubs

- WSDL2WS tool that generates wrappers, which perform the following functions. These wrappers act as RPC Providers.

- Serialization

- Deserialization

- Method invocation

- WSDLs hosted statistically in the server.

- Standalone server (with HTTP support)

- Web server modules for Apache 1.3 & (Linux/Windows)

- Basic Wrapper Class Generator tool with following functionalities.

- Wrapping existing systems as web services

- WSDL generation

- Web interface to the deployed services and their WSDL s.

- Sample web services and client applications.

Axis C++ now delivers the following key features

- Speed: Axis uses SAX (event-based) parsing to acheive significantly greater speed than earlier versions of Apache

SOAP.

- Flexibility

- Stability , Component oriented Deployment

- Transport Framework

- WSDL support

AxisC++ 1.0supports the Web Service Description Language, version 1.1, which allows you to easily build stubs to access remote services, and also to automatically export machine-readable descriptions of your deployed services from Axis. We hope you enjoy using Axis c++ 1.0. Please note that this is an open-source effort - if you feel the code could use some new features or fixes, please get involved and lend a hand! The Axis developer community welcomes your participation. Let us know what you think! Please send feedback about the package to axis-user@xml.apache.org

What's Missing ?

Full SOAP 1.2 support.

Installing Axis and Using this Guide

See the Axis Installation Guide for instructions on installing Axis C++

Sample tests using InteropBase.wsdl: for Linux Users

Before running the examples in this guide, you'll need to make sure that your environment variables and other configurations are set correctly as described in Installation guide. That is you need

- Axis C++

- Apache1.3 (or Apache2.0)

- xerces-C

- j2SDK1.4

installed and configured.

Download Source Distribution

Let's take a look at a sample InteropBase service client that will call methods of a InteropBase service deployed on Axis C++. You can find the InteropBase.wsdl for this example at

$AXISCPP_HOME/samples/client/interoptests/base

When starting with the valid WSDL file to use Axis C++ you have to get started with the tool called WSDL2Ws which is written in Java. source for WSDL2Ws tool is in

$AXISCPP_HOME/src/wsdl

You need the following jar files included in the CLASSPATH .

- axis.jar

- commons-discovery.jar

- commons-logging.jar

- jaxrpc.jar

- saaj.jar

- wsdl4j.jar

- xml-apis.jar

The CLASSPATH Environment Variable should have the absolute paths of the jars (including the jar file name) given as a colon separated list

Here is a sample /home/axisuser/.bash_profile file where we specified those

AXIS_JARS_HOME="$AXISCPP_HOME/lib/axisjava"

AXIS_JARS="$AXIS_JARS_HOME/axis-
ant.jar:$AXIS_JARS_HOME/axis.jar:$AXIS_JARS_HOME/commons-
discovery.jar:$AXIS_JARS_HOME/commons-
logging.jar:$AXIS_JARS_HOME/jaxrpc.jar:$AXIS_JARS_HOME/log4j-
1.2.4.jar:$AXIS_JARS_HOME/saaj.jar:$AXIS_JARS_HOME/wsdl4j.jar"

JAVA_HOME="/usr/java"

PATH="$PATH:$JAVA_HOME/bin:."

CLASSPATH="$CLASSPATH:./:$JAVA_HOME/lib:$AXIS_JARS:"

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC AXIS_JARS_HOME

AXIS_JARS JAVA_HOME CLASSPATH

Now

$ cd $AXISCPP_HOME/src/wsdl/

$ mkdir temp

$javac -d ./temp -sourcepath . ./org/apache/axis/wsdl/wsdl2ws/*.java

$cd temp

$jar -cvf wsdl2ws.jar org

$cp -f wsdl2ws.jar $AXISCPP_HOME/lib/axis

add this jar to the classpath as well.

Server side Skeleton And Wrappers Generated by the wsdl2ws Tool

We use the sample at

$AXISCPP_HOME/samples/server/interoptests/base.

We use this sample to demonstrate the generation of serverside skeletons and how to deploy a web service using it.

Inside this folder you will find InteropBase.wsdl file using which we generate skeleton and Wrappers. Here is the command line arguments to generate the skeleton.

cd $AXISCPP_HOME/samples/server/interoptests/base

% java org.apache.axis.wsdl.wsdl2ws.WSDL2Ws InteropBase.wsdl -lc++ -sserver

Note: If you give -o. /GenClassesServer then the server create a folder named GenClassServer and put the source there. Otherwise the source is put in the current folder where the tool is run.

In this sample it generates

- ArrayOffloat.h

- ArrayOfint.h

- ArrayOfSOAPStruct.h

- ArrayOfstring.h

- InteropTestPortType.h

- InteropTestPortTypeWrapper.h

- SOAPStruct.h

- InteropTestPortType.cpp

- InteropTestPortTypeService.cpp

- InteropTestPortTypeWrapper.cpp

- SOAPStruct.cpp

You can fill skeltons with your business logic. In this example it is done for you in InteropTestPortType.Cpp

////////////////////////////////////

//This is the Service implementation CPP file genarated by theWSDL2Ws.

// InteropTestPortType.cpp: implemtation for the InteropTestPortType.

//

////////////////////////////////////

#include "InteropTestPortType.h"

InteropTestPortType::InteropTestPortType()

{

}

InteropTestPortType::~InteropTestPortType()

{

}

string InteropTestPortType::echoString(string Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOfstring InteropTestPortType::echoStringArray(ArrayOfstring Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

int InteropTestPortType::echoInteger(int Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

}

ArrayOfint InteropTestPortType::echoIntegerArray(ArrayOfint Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

float InteropTestPortType::echoFloat(float Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOffloat InteropTestPortType::echoFloatArray(ArrayOffloat Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

SOAPStruct* InteropTestPortType::echoStruct(SOAPStruct* Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOfSOAPStruct InteropTestPortType::echoStructArray(ArrayOfSOAPStruct Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

void InteropTestPortType::echoVoid()

{

}

Axis_Base64Binary InteropTestPortType::echoBase64(Axis_Base64Binary Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_DateTime InteropTestPortType::echoDate(Axis_DateTime Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_HexBinary InteropTestPortType::echoHexBinary(Axis_HexBinary Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_Decimal InteropTestPortType::echoDecimal(Axis_Decimal Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_Boolean InteropTestPortType::echoBoolean(Axis_Boolean Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Deploying the Service

The Folder called deploy in the $AXISCPP_HOME/ should be copied to apache root folder .Rename the deploy folder as "Axis". Give all permissions to this folder.

$ cp –rf $AXISCPP_HOME/deploy /usr/local/apache

$ cd /usr/local/apache

$ mv deploy Axis

$ chmod -R 777 Axis

Now set the environment variable AXIS_HOME pointing to this directory.

AXIS_HOME="/usr/local/apache/Axis"

Note that inside $AXIS_HOME directory there is a file called axiscpp.conf. Make sure that it has read permissions. This file contains key, value pairs of paths used by the Axis Soap Engine. You can change the WSDDFILEPATH and AXISLOGPATH inside this file according to your choice.

Type the Following Command to build the service(You can always use makefiles instead of the following commands to build.)

cd $AXISCPP_HOME/samples/server/introptests/base

$ g++ -DHAVE_CONFIG_H -I. -I. -I.. -I$AXISCPP_HOME/include -Wshadow -Wall

-pedantic -ansi -g -O2 -c ./*.cpp -fPIC

$ g++ -shared -Wl,--whole-archive -Wl,--no-whole-archive -I. -I.. -L$AXISCPP_HOME/lib/xerces-c

-lxerces-c -Wl,-soname -Wl,libinteropbase.so.0 -o libinteropbase.so ./*.o

By typing this in the command line the dynamic library ( libinteropbase.so for example) is created which is used for the deployment. This library has to be placed in

$AXIS_HOME/webservices where $AXIS_HOME = /usr/local/apache/Axis

Modify the server.wsdd. Modify the server.wsdd appropriate for your service. (You have a sample server.wsdd file given below appropriately filled for this service).

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"xmlns:C="http://xml.apache.org/axis/wsdd/providers/c">

< service name="InteropBase" provider="C:RPC" description="SOAPBuilders Interoperability Lab Round 2 base test suite described at http://www.whitemesa.com/interop/proposal2.html ">
< parameter name="allowedMethods" value="echoString EchoInt echoStringArray echoInteger echoIntegerArray echoFloat echoFloatArray echoStruct echoStructArray echoVoid echoBase64 echoDate echoHexBinary echoDecimal echoBoolean "/>
< parameter name="className" value="/usr/local/apache/Axis/webservices/libinteropbase.so"/>
< /service>
</deployment>

Note: You should make a backup of $AXIS_HOME/conf/server.wsdd and edit the original file so that it is exactly as above.

server.wsdd should be in

/usr/local/apache/Axis/conf/

Start the Apache server

$ /usr/local/apache/bin/apachectl start

Now open a browser and enter the link http://localhost:80/axis If the service is correctly deployed then it will be displayed in a table of deployed services which contain information such as service name, link to wsdl and a description of the service.

Client side Stubs Generated by the wsdl2ws Tool

WSDL2Ws tools will generate the stubs for the client side. You will have C++ Client class and header file.

cd $AXISCPP_HOME/samples/client/interoptests/base

$ java org.apache.axis.wsdl.wsdl2ws.WSDL2Ws InteropBase.wsdl -lc++ -sclient

Note: again if you specify -o./GenClassesClient you will have source generated inside GenClassClient folder instead of current folder where the tool is run. Before compiling the client you have to write a class which contain a main method in which InteropTestPortType instance is created and its methods are called.

// InteropBaseClient.cpp : Defines the entry point for the console application.

//

#include "InteropTestPortType.h"

#define ARRAYSIZE 2

int main(int argc, char* argv[])

{

int x;

char buffer[100];

InteropTestPortType ws;

printf("invoking echoString...\n");

//testing echoString

if (ws.echoString("hello world") == "hello world")

printf("successful\n");

else

printf("failed\n");

// testing echoStringArray

ArrayOfstring arrstr;

arrstr.m_Array = new string[ARRAYSIZE];

arrstr.m_Size = ARRAYSIZE;

for (x=0;x {

sprintf(buffer, "%dth element of string array", x);

arrstr.m_Array[x] = buffer;

}

printf("invoking echoStringArray...\n");

if (ws.echoStringArray(arrstr).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echoInteger

printf("invoking echoInteger...\n");

if (ws.echoInteger(56) == 56)

printf("successful\n");

else

printf("failed\n");

// testing echoIntegerArray

ArrayOfint arrint;

arrint.m_Array = new int[ARRAYSIZE];

arrint.m_Size = ARRAYSIZE;

for (x=0;x {

arrint.m_Array[x] = x;

}

printf("invoking echoIntegerArray...\n");

if (ws.echoIntegerArray(arrint).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echoFloat

printf("invoking echoFloat...\n");

if (ws.echoFloat(1.4214) > 1.42)

printf("successful\n");

else

printf("failed\n");

// testing echoFloat

ArrayOffloat arrfloat;

arrfloat.m_Array = new float[ARRAYSIZE];

arrfloat.m_Size = ARRAYSIZE;

for (x=0;x {

arrfloat.m_Array[x] = 1.1111*x;

}

printf("invoking echoFloatArray...\n");

if (ws.echoFloatArray(arrfloat).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echo Struct

SOAPStruct stct;

stct.varFloat = 12345.7346345;

stct.varInt = 5000;

stct.varString = "This is string in SOAPStruct";

printf("invoking echoStruct...\n");

if (ws.echoStruct(&amp;stct) != NULL)

printf("successful\n");

else

printf("failed\n");

//testing echo Array of Struct

ArrayOfSOAPStruct arrstct;

arrstct.m_Array = new SOAPStruct[ARRAYSIZE];

arrstct.m_Size = ARRAYSIZE;

for (x=0;x {

arrstct.m_Array[x].varFloat = 1.1111*x;

arrstct.m_Array[x].varInt = x;

sprintf(buffer, "varString of %dth element of SOAPStruct array", x);

arrstct.m_Array[x].varString = buffer;

}

//testing echo Struct Array

printf("invoking echoStructArray...\n");

if (ws.echoStructArray(arrstct).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

//testing echo void

printf("invoking echoVoid...\n");

ws.echoVoid();

printf("successful\n");

//testing echo base 64 binary

printf("invoking echoBase64...\n");

if (ws.echoBase64("

BCDF675E234242WHRTKMJDGKGUEJ898636JFJFHEJDGWTDHFJRURYGBCDHTWRSG")

=="BCDF675E234242WHRTKMJDGKGUEJ898636JFJFHEJDGWTDHFJRURYGBCDHTWRSG")
printf("successful\n");

else

printf("failed\n");

time_t tim;

time(&amp;tim);

tm* lt = gmtime(&amp;tim);

printf("invoking echoDate...\n");

if (memcmp(&amp;ws.echoDate(*lt), lt, sizeof(tm)) == 0)

printf("successful\n");

else

printf("failed\n");

//testing echo hex binary

printf("invoking echoHexBinary...\n");

if (ws.echoHexBinary("CCCFFA46552BC7D5A09BC5F23DE9E0FE7862AD45BC87D02FEE") ==

"CCCFFA46552BC7D5A09BC5F23DE9E0FE7862AD45BC87D02FEE")

printf("successful\n");

else

printf("failed\n");

//testing echo decimal

printf("invoking echoDecimal...\n");

if (ws.echoDecimal(1234.567890) > 1234.56)

printf("successful\n");

else

printf("failed\n");

//testing echo boolean

printf("invoking echoBoolean...\n");

if (ws.echoBoolean(1) == 1)

printf("successful\n");

else

printf("failed\n");

getchar();

return 0;

}

Creating the client library

cd $AXISCPP_HOME/src/client

$sh autogen.sh

$sh runconfig

$make

$make install

This will automatically create libaxiscpp_client.so and copy it to the $AXISCPP_HOME/bin (as configured in runconfig script)

Now

cd $AXISCPP_HOME/samples/client/interoptests/base

$ g++ -DHAVE_CONFIG_H -I. -I. -I.. -I$AXISCPP_HOME/include -Wshadow -Wall -pedantic
- ansi -g -O2 -c ./*.cpp -fPIC

$ g++ -g -O2 -o interopbase InteropBaseClient.o SOAPStruct.o InteropTestPortType.o $AXISCPP_HOME/lib/axis/libaxiscpp_client.a $AXISCPP_HOME/bin/libaxiscpp_mod.a -L$AXISCPP_HOME/lib/xerces-c -lxerces-c -ldl

Note that in the above command replace libaxiscpp_mod.a with libaxiscpp_mod2.a if you work with apache2

Start the Apache Server(Assuming base service is deployed.)

$ /usr/local/apache/bin/apachectl start

to run

$ cd $AXISCPP_HOME/samples/client/interoptests/base

$ ./interopbase

Handler Sample

If you want to test handlers go into the $AXISCPP_HOME/src/server/handlers folder where example handlers are included. Several sample handlers are included there covering the concepts of service specific, global and transport handlers. We will show you the detail of running a service specific handler named loghandler. The task of this handler is writing to a file the number of times the service is accessed.

cd $AXISCPP_HOME/src/server/handlers/custom/loghandler

$sh autogen.sh

$sh runconfig

$make

$make install

The handler library will be installed at $(AXIS_HOME)/handlers/custom/loghandler Now edit the $(AXIS_HOME)/conf/server.wsdd to include the handler for a particular service.

<service name="InteropBase" provider="C:RPC" description="SOAPBuilders Interoperability Lab Round
2 base test suite described at http://www.whitemesa.com/interop/proposal2.html ">
<requestFlow name="calchandlers">
<handler name="LogAccessCount"
type="/usr/local/apache/Axis/handlers/custom/loghandler/libloghandler.so">
<parameter name="logAccessCountFile"
value="/usr/local/apache/Axis/handlers/custom/loghandler/LogAccessCountFile"/>
</handler>
</requestFlow>
<parameter name="allowedMethods" value="echoString EchoInt echoStringArray
echoInteger echoIntegerArray echoFloat echoFloatArray echoStruct echoStructArray echoVoid
echoBase64 echoDate echoHexBinary echoDecimal echoBoolean "/>
<parameter name="className" value="/usr/local/apache/Axis/webservices/libinteropbase.so"/>
</service>

Restart the apache web server and test your handler using the web service client for InteropBase webservice. When the client is run an entry will be added to $AXIS_HOME/handlers/custom/loghandler/LogAccessCountFile Note that the folder in which the LogAccessCountFile is created should have write access. You can test the global handlers and transport handlers in a similar manner. Note the change you have to make in server.wsdd. You can see how this is done in the specimen folder $AXISCPP_HOME/deploy/conf/server.wsdd.

Download Binary Distribution

Let's take a look at a sample InteropBase service client that will call methods of a InteropBase service deployed on Axis C++. You can find the InteropBase.wsdl for this example at

$AXISCPP_HOME/deploy/wsdls

You need the following jar files included in the CLASSPATH .

- axis.jar

- commons-discovery.jar

- commons-logging.jar

- jaxrpc.jar

- saaj.jar

- wsdl4j.jar

- xml-apis.jar

The CLASSPATH Environment Variable should have the absolute paths of the jars (including the jar file name) given as a colon separated list

Here is a sample /home/axisuser/.bash_profile file where we specified those

AXIS_JARS_HOME="$AXISCPP_HOME/lib/axisjava"

AXIS_JARS="$AXIS_JARS_HOME/axis-
ant.jar:$AXIS_JARS_HOME/axis.jar:$AXIS_JARS_HOME/commons-
discovery.jar:$AXIS_JARS_HOME/commons-
logging.jar:$AXIS_JARS_HOME/jaxrpc.jar:$AXIS_JARS_HOME/log4j-
1.2.4.jar:$AXIS_JARS_HOME/saaj.jar:$AXIS_JARS_HOME/wsdl4j.jar"

JAVA_HOME="/usr/java"

PATH="$PATH:$JAVA_HOME/bin:."

CLASSPATH="$CLASSPATH:./:$JAVA_HOME/lib:$AXIS_JARS:$AXISCPP_HOME/lib/axis/wsdl2ws.jar"

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC AXIS_JARS_HOME

AXIS_JARS JAVA_HOME CLASSPATH

Server side Skeleton And Wrappers Generated by the wsdl2ws Tool .

We use the sample at

$AXISCPP_HOME/samples/server/interoptests/base.

We use this sample to demonstrate the generation of serverside skeletons and how to deploy a web service using it.

Inside this folder you will find InteropBase.wsdl file using which we generate skeleton and Wrappers. Here is the command line arguments to generate the skeleton.

cd $AXISCPP_HOME/samples/server/interoptests/base

% java org.apache.axis.wsdl.wsdl2ws.WSDL2Ws InteropBase.wsdl -lc++ -sserver

Note: If you give -o. /GenClassesServer then the server create a folder named GenClassServer and put the source there. Otherwise the source is put in the current folder where the tool is run.

In this sample it generates

- ArrayOffloat.h

- ArrayOfint.h

- ArrayOfSOAPStruct.h

- ArrayOfstring.h

- InteropTestPortType.h

- InteropTestPortTypeWrapper.h

- SOAPStruct.h

- InteropTestPortType.cpp

- InteropTestPortTypeService.cpp

- InteropTestPortTypeWrapper.cpp

- SOAPStruct.cpp

You can fill skeltons with your business logic. In this example it is done for you in InteropTestPortType.Cpp

/////////////////////////////////

//This is the Service implementation CPP file genarated by theWSDL2Ws.

// InteropTestPortType.cpp: implemtation for the InteropTestPortType.

//

////////////////////////////////

#include "InteropTestPortType.h"

InteropTestPortType::InteropTestPortType()

{

}

InteropTestPortType::~InteropTestPortType()

{

}

string InteropTestPortType::echoString(string Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOfstring InteropTestPortType::echoStringArray(ArrayOfstring Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

int InteropTestPortType::echoInteger(int Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

}

ArrayOfint InteropTestPortType::echoIntegerArray(ArrayOfint Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

float InteropTestPortType::echoFloat(float Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOffloat InteropTestPortType::echoFloatArray(ArrayOffloat Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

SOAPStruct* InteropTestPortType::echoStruct(SOAPStruct* Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

ArrayOfSOAPStruct InteropTestPortType::echoStructArray(ArrayOfSOAPStruct Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

void InteropTestPortType::echoVoid()

{

}

Axis_Base64Binary InteropTestPortType::echoBase64(Axis_Base64Binary Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_DateTime InteropTestPortType::echoDate(Axis_DateTime Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_HexBinary InteropTestPortType::echoHexBinary(Axis_HexBinary Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_Decimal InteropTestPortType::echoDecimal(Axis_Decimal Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Axis_Boolean InteropTestPortType::echoBoolean(Axis_Boolean Value0)

{

//Following line is not generated. You have to fill it. Here it is filled for you.

return Value0;

}

Deploying the Services

The Folder called deploy in the $AXISCPP_HOME should be copied to apache root folder .Rename the deploy folder as "Axis". Give all permissions to this folder.

$ cp –rf $AXISCPP_HOME/deploy /usr/local/apache

$ cd /usr/local/apache

$ mv deploy Axis

$ chmod -R 777 Axis

Now set the environment variable AXIS_HOME pointing to this directory.

AXIS_HOME="/usr/local/apache/Axis"

Type the Following Command to build the service(You can always use makefiles instead of the following commands to build.)

cd $AXISCPP_HOME/samples/server/introptests/base

$ g++ -DHAVE_CONFIG_H -I. -I. -I.. -I$AXISCPP_HOME/include -Wshadow -Wall
-pedantic -ansi -g -O2 -c ./*.cpp -fPIC

$ g++ -shared -Wl,--whole-archive -Wl,--no-whole-archive -I. -I.. -L$AXISCPP_HOME/lib/xerces-c -lxerces-c -Wl,-soname -Wl,libinteropbase.so.0 -o libinteropbase.so ./*.o

By typing this in the command line the dynamic library ( libinteropbase.so for example) is created which is used for the deployment. This library has to be placed in

$AXIS_HOME/webservices where $AXIS_HOME = /usr/local/apache/Axis

Modify the server.wsdd. Modify the server.wsdd appropriate for your service. (You have a sample server.wsdd file given below appropriately filled for this service).

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:C="http://xml.apache.org/axis/wsdd/providers/c">


< service name="InteropBase" provider="C:RPC" description="SOAPBuilders Interoperability Lab Round 2 base test suite described at http://www.whitemesa.com/interop/proposal2.html ">
< parameter name="allowedMethods" value="echoString EchoInt echoStringArray echoInteger echoIntegerArray echoFloat echoFloatArray echoStruct echoStructArray echoVoid echoBase64 echoDate echoHexBinary echoDecimal echoBoolean "/>
< parameter name="className" value="/usr/local/apache/Axis/webservices/libinteropbase.so"/>
< /service>
</deployment>

Note: You should make a backup of $AXIS_HOME/conf/server.wsdd and edit the original file so that it is exactly as above.

server.wsdd should be in

usr/local/apache/Axis/conf/

Start the Apache server

$ usr/local/apache/bin/apachectl start

Now open a browser and enter the link http://localhost:80/axis If the service is correctly deployed then it will be displayed in a table of deployed services which contain information such as service name, link to wsdl and a description of the service.

Client side Stubs Generated by the wsdl2ws Tool

WSDL2Ws tools will generate the stubs for the client side. You will have C++ Client class and header file.

cd $AXISCPP_HOME/samples/client/interoptests/base

$ java org.apache.axis.wsdl.wsdl2ws.WSDL2Ws InteropBase.wsdl -lc++ -sclient

Note: again if you specify -o./GenClassesClient you will have source generated inside GenClassClient folder instead of current folder where the tool is run. Before compiling the client you have to write a class which contain a main method in which InteropTestPortType instance is created and its methods are called.

// InteropBaseClient.cpp : Defines the entry point for the console application.

//

#include "InteropTestPortType.h"

#define ARRAYSIZE 2

int main(int argc, char* argv[])

{

int x;

char buffer[100];

InteropTestPortType ws;

printf("invoking echoString...\n");

//testing echoString

if (ws.echoString("hello world") == "hello world")

printf("successful\n");

else

printf("failed\n");

// testing echoStringArray

ArrayOfstring arrstr;

arrstr.m_Array = new string[ARRAYSIZE];

arrstr.m_Size = ARRAYSIZE;

for (x=0;x {

sprintf(buffer, "%dth element of string array", x);

arrstr.m_Array[x] = buffer;

}

printf("invoking echoStringArray...\n");

if (ws.echoStringArray(arrstr).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echoInteger

printf("invoking echoInteger...\n");

if (ws.echoInteger(56) == 56)

printf("successful\n");

else

printf("failed\n");

// testing echoIntegerArray

ArrayOfint arrint;

arrint.m_Array = new int[ARRAYSIZE];

arrint.m_Size = ARRAYSIZE;

for (x=0;x {

arrint.m_Array[x] = x;

}

printf("invoking echoIntegerArray...\n");

if (ws.echoIntegerArray(arrint).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echoFloat

printf("invoking echoFloat...\n");

if (ws.echoFloat(1.4214) > 1.42)

printf("successful\n");

else

printf("failed\n");

// testing echoFloat

ArrayOffloat arrfloat;

arrfloat.m_Array = new float[ARRAYSIZE];

arrfloat.m_Size = ARRAYSIZE;

for (x=0;x {

arrfloat.m_Array[x] = 1.1111*x;

}

printf("invoking echoFloatArray...\n");

if (ws.echoFloatArray(arrfloat).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

// testing echo Struct

SOAPStruct stct;

stct.varFloat = 12345.7346345;

stct.varInt = 5000;

stct.varString = "This is string in SOAPStruct";

printf("invoking echoStruct...\n");

if (ws.echoStruct(&amp;stct) != NULL)

printf("successful\n");

else

printf("failed\n");

//testing echo Array of Struct

ArrayOfSOAPStruct arrstct;

arrstct.m_Array = new SOAPStruct[ARRAYSIZE];

arrstct.m_Size = ARRAYSIZE;

for (x=0;x {

arrstct.m_Array[x].varFloat = 1.1111*x;

arrstct.m_Array[x].varInt = x;

sprintf(buffer, "varString of %dth element of SOAPStruct array", x);

arrstct.m_Array[x].varString = buffer;

}

//testing echo Struct Array

printf("invoking echoStructArray...\n");

if (ws.echoStructArray(arrstct).m_Array != NULL)

printf("successful\n");

else

printf("failed\n");

//testing echo void

printf("invoking echoVoid...\n");

ws.echoVoid();

printf("successful\n");

//testing echo base 64 binary

printf("invoking echoBase64...\n");

if (ws.echoBase64("

BCDF675E234242WHRTKMJDGKGUEJ898636JFJFHEJDGWTDHFJRURYGBCDHTWRSG")

=="BCDF675E234242WHRTKMJDGKGUEJ898636JFJFHEJDGWTDHFJRURYGBCDHTWRSG")
printf("successful\n");

else

printf("failed\n");

time_t tim;

time(&amp;tim);

tm* lt = gmtime(&amp;tim);

printf("invoking echoDate...\n");

if (memcmp(&amp;ws.echoDate(*lt), lt, sizeof(tm)) == 0)

printf("successful\n");

else

printf("failed\n");

//testing echo hex binary

printf("invoking echoHexBinary...\n");

if (ws.echoHexBinary("
CCCFFA46552BC7D5A09BC5F23DE9E0FE7862AD45BC87D02FEE") ==

"CCCFFA46552BC7D5A09BC5F23DE9E0FE7862AD45BC87D02FEE")

printf("successful\n");

else

printf("failed\n");

//testing echo decimal

printf("invoking echoDecimal...\n");

if (ws.echoDecimal(1234.567890) > 1234.56)

printf("successful\n");

else

printf("failed\n");

//testing echo boolean

printf("invoking echoBoolean...\n");

if (ws.echoBoolean(1) == 1)

printf("successful\n");

else

printf("failed\n");

getchar();

return 0;

}

You will find the client libraries required to run the sample client installed in $AXISCPP_HOME/lib/axis

Now

cd $AXISCPP_HOME/samples/client/interoptests/base

$ g++ -DHAVE_CONFIG_H -I. -I. -I.. -I$AXISCPP_HOME/include -Wshadow -Wall -pedantic
- ansi -g -O2 -c ./*.cpp -fPIC

$ g++ -g -O2 -o interopbase InteropBaseClient.o SOAPStruct.o InteropTestPortType.o $AXISCPP_HOME/lib/axis/libaxiscpp_client.a $AXISCPP_HOME/bin/libaxiscpp_mod.a -L$AXISCPP_HOME/lib/xerces-c -lxerces-c -ldl

Note that in the above command replace libaxiscpp_mod.a with libaxiscpp_mod2.a if you work with apache2

Start the Apache Server(Assuming base service is deployed.)

$ /usr/local/apache/bin/apachectl start

To Run

$ cd $AXISCPP_HOME/samples/client/interoptests/base

$ ./interopbase

Handler Sample

Sample handler libraries are included in $(AXISCPP_HOME)/src/server/handlers folder. Several sample handlers are included there covering the concepts of service specific, global and transport handlers. We will show you the detail of running a service specific handler named loghandler. The task of this handler is writing to a file the number of times the service is accessed.

cp -rf $AXISCPP_HOME/deploy/handlers $(AXIS_HOME)/

<service name="InteropBase" provider="C:RPC" description="SOAPBuilders Interoperability Lab Round
2 base test suite described at http://www.whitemesa.com/interop/proposal2.html ">
<requestFlow name="calchandlers">
<handler name="LogAccessCount"
type="/usr/local/apache/Axis/handlers/custom/loghandler/libloghandler.so">
<parameter name="logAccessCountFile"
value="/usr/local/apache/Axis/handlers/custom/loghandler/LogAccessCountFile"/>
</handler>
</requestFlow>
<parameter name="allowedMethods" value="echoString EchoInt echoStringArray
echoInteger echoIntegerArray echoFloat echoFloatArray echoStruct echoStructArray echoVoid
echoBase64 echoDate echoHexBinary echoDecimal echoBoolean "/>
<parameter name="className" value="/usr/local/apache/Axis/webservices/libinteropbase.so"/>
</service>

Restart the apache web server and test your handler using the web service client for InteropBase webservice. When the client is run an entry will be added to /usr/local/apache/Axis/handlers/custom/loghandler/LogAccessCountFile Note that the folder in which the LogAccessCountFile is created should have write access. You can test the global handlers and transport handlers in a similar manner. Note the change you have to make in server.wsdd. You can see how this is done in the specimen folder $(AXISCPP_HOME)/deploy/conf/server.wsdd.

TODO: document how the users can write their own handlers and webservices. For the time being users can refer to the samples given and follow their example to write their own handlers and webservices. This task is fairly easy if you follow the examples.

You can use the tcpmon program of Axis Java to view what goes on the wire when a soap transaction is taking place. Please visit http://ws.apache.org/axis/ and get Axis java, to obtain tcpmon.

Your contribution to Axis C++ as a developer, tester is highly appreciated. You can download the latest source from the cvs repository as documented below.

Getting a CVS checkout

Visit http://ws.apache.org/ click on "axis" and then on "CVS Repository" to find details on accessing the CVS Repository. It will have instructions similar to the following."Anyone can checkout source code from our anonymous CVS server. To do so, simply use the following commands (if you are using a GUI CVS client, configure it appropriately):

cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login

password: anoncvs

cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout ws-axis"

The examples given below will be based on these lines of instructions.

To use the command line cvs client go to http://www.cvshome.org and download the cvs binaries for windows. Extract the cvs binaries from the downloaded zip file. There will be a "cvs.exe" file when this is extracted. Set the PATH environment variable to where "cvs.exe" is. You would have to do the following to get a checkout from the command line cvs client.

cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login

Now you will be prompted for the password. Enter the password.

password: anoncvs

Now enter the following cvs command to checkout the axis Repository.

cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout ws-axis

The checkout of the repository will be created in the current directory in a folder named ȁc;ws-axisȁd;