blob: 35d544766ac03dab9c80057e7bc49f483e1c1b76 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><title>Axis2/C - Axis2/C User's Guide</title><style type="text/css" media="all">
@import url("../style/maven-base.css");
@import url("../style/maven-classic.css");</style><link rel="stylesheet" href="../style/print.css" type="text/css" media="print"></link><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta></head><body class="composite"><div id="banner"><a href="http://www.apache.org/" id="organizationLogo"><img alt="Apache Software Foundation" src="http://www.apache.org/images/asf-logo.gif"></img></a><a href="http://ws.apache.org/axis2/c" id="projectLogo"><img alt="Apache Axis2 C" src="http://ws.apache.org/axis2/images/axis.jpg"></img></a><div class="clear"><hr></hr></div></div><div id="breadcrumbs"><div class="xleft">
Last published: 22 December 2006
| Doc for 0.96</div><div class="xright"></div><div class="clear"><hr></hr></div></div><div id="leftColumn"><div id="navcolumn"><div id="menuAxis2_C"><h5>Axis2/C</h5><ul><li class="none"><a href="../index.html">Home</a></li><li class="expanded"><a href="../download.cgi">Download Axis2/C</a><ul><li class="none"><a href="../download.cgi">Releases</a></li><li class="none"><a href="http://svn.apache.org/viewvc/axis/axis2/c/core/trunk/" class="externalLink" title="External Link">View Source Code Online</a></li><li class="none"><a href="../svn.html">Checkout Source Code</a></li></ul></li><li class="expanded"><a href="../docs/index.html">Documentation</a><ul><li class="none"><a href="../docs/installationguide.html">Installation Guide</a></li><li class="none"><a href="../docs/developerguide.html">Developer Guide</a></li><li class="none"><a href="../docs/userguide.html">User Guide</a></li><li class="none"><a href="../docs/axis2c_manual.html">Axis2/C manual</a></li></ul></li><li class="expanded"><a href="../mail-lists.html">Get Involved</a><ul><li class="none"><a href="../mail-lists.html">Mailing Lists</a></li></ul></li><li class="expanded"><a href="../team-list.html">Project Information</a><ul><li class="none"><a href="../team-list.html">Project Team</a></li><li class="none"><a href="../issue-tracking.html">Issue Tracking</a></li></ul></li></ul></div><a href="http://maven.apache.org/" title="Built by Maven" id="poweredBy"><img alt="Built by Maven" src="../images/logos/maven-button-1.png"></img></a></div></div><div id="bodyColumn"><div class="contentBox"><div class="section"><a name="Apache_Axis2_C_User_s_Guide"></a><h2>Apache Axis2/C User's Guide</h2><div class="subsection"><a name="Content"></a><h3>Content</h3><ul>
<li><p><a href="#Introduction">Introduction</a></p>
<ul>
<li><a href="#What_is_Axis2_">What is Axis2/C?</a></li>
</ul>
</li>
<li><a href="#Web_Services_Using_Axis2">Web Services Using Axis2/C</a>
<ul>
<li><a href="#Writing_Web_Services_Using_Axis2_C">Writing Web Services
Using Axis2/C</a>
<ul>
<li><a href="#Creating_Web_Service__MyService_">Creating Web
Service (Echo service)</a></li>
<li><a href="#How_to_write_the_Web_Service_">How to write the Web
Service?</a>
<ul>
<li><a href="#Step1">Step1 :Write the echo_skeleton.c file
implementing the axis2_svc_skeleton.h</a></li>
<li><a href="#Step2">Step2 :Now we can write the echo service
in a file echo.c</a></li>
<li><a href="#Step3">Step3 :Write the services.xml file</a></li>
<li><a href="#Step4">Step4 :Create the Web Service
Folder</a></li>
<li><a href="#Step5">Step5 :Archive based deployment
model</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#Writing_Web_Services_Using_Code_Generator">Writing Web
Services Skeleton Using Code Generator</a>
<ul>
<li><a href="#WSDL2C_tool">WSDL2C tool</a></li>
<li><a href="#Implement_the_Business_Logic">Implement the Business
Logic</a></li>
<li><a href="#echoString">echoString</a></li>
<li><a href="#echoStringArray">echoStringArray</a></li>
<li><a href="#echoStruct">echoStruct</a></li>
<li><a href="#services_xml">services.xml</a></li>
</ul>
</li>
<li><a href="#deploy">Deploy the Web Service</a></li>
</ul>
</li>
<li><p><a href="#Web_Service_Clients_Using_Axis2">Web Service Clients Using
Axis2/C</a></p>
<ul>
<li><a href="#Writing_Web_Service_Clients_using_Axis2%27s_Primary_APIs">Writing
Web Service Clients Using Axis2's Primary APIs</a>
<ul>
<li><a href="#EchoBlockingClient">echo_blocking Client</a></li>
<li><a href="#EchoNonBlockingClient">echo_non_blocking
Client</a></li>
<li><a href="#EchoNonBlockingDualClient">echo_non_blocking_dual
Client</a></li>
<li><a href="#EchoBlockingDualClient">echo_blocking_dual
Client</a></li>
</ul>
</li>
<li><a href="#Writing_Web_Clients_Using_Code_Generator">Writing Web
Service Clients using Code Generation with Data Binding Support</a>
<ul>
<li><a href="#Codegenerator_Client_echoString">Client for
echoString operation</a></li>
<li><a href="#Codegenerator_Client_echoStringArray">Client for
echoStringArray operation</a></li>
<li><a href="#Codegenerator_Client_echoStruct">Client for
echoStruct operation</a></li>
</ul>
</li>
</ul>
</li>
<li><p><a href="#Providing_security_using_Rampart">Providing security using
Rampart/C</a></p>
<ul>
<li><a href="#Engaging_rampart_module">Engaging rampart module</a></li>
<li><a href="#Semantics_of_parameters_specified_in_axis2_xml">Semantics
of parameters specified in axis2.xml</a></li>
<li><a href="#Writing_own_password_callback_module">Writing own
password callback module</a></li>
<li><a href="#Adding_security_parameters_dynamically">Adding security
parameters dynamically</a></li>
</ul>
</li>
</ul><p><a id="Introduction"></a></p></div><div class="subsection"><a name="Introduction"></a><h3>Introduction</h3><p>Welcome to Axis2/C, the Apache Axis2 implementation in C. This User's Guide
will help you understand what Axis2/C has to offer and how to get started
with it.</p><p><a id="What_is_Axis2_"></a></p></div><div class="subsection"><a name="What_is_Axis2_C_"></a><h3>What is Axis2/C?</h3><p>Axis2/C is an effort to implement the <a href="http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html" class="externalLink" title="External Link">Axis2
architecture</a> in C programming language. For more information on the
architecture <a href="architecture_notes.html">C Specific Architectural
Notes</a> are also available.</p><p>After months of continued discussion and coding in this direction, Axis2/C
now delivers the following key features:</p><ul>
<li><p style="margin-bottom: 0in;"><strong>Speed</strong> - Axis2/C uses
its own XML object model and StAX (Streaming API for XML) parsing to
achieve significant speed. In addition to that, Axis2/C is inherently
benefited by the speed of its implementation language, namely C, compared
to Java implementation.</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>Low memory foot print</strong>-
Axis2 architecture was designed ground-up keeping in mind the low memory foot
print. Axis2/C strives to achieve the same with a well designed
memory management strategy.</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>AXIOM/C</strong>- Axis2/C comes
with its own light-weight object model for XML, AXIOM/C which is the C
implementation of <a href="http://ws.apache.org/commons/axiom/OMTutorial.html" class="externalLink" title="External Link">AXIOM</a>.</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>MEP Support</strong> - Supports
Message Exchange Patterns (MEPs)</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>Flexibility</strong> - Axis2/C
architecture gives the developer complete freedom to insert
extensions into the engine (using modules and handlers) for custom SOAP
header processing.</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>Transport Framework</strong> -
We have a clean and simple abstraction for integrating and using
transports, and the core of the engine is completely
transport-independent.</p>
</li>
<li><p style="margin-bottom: 0in;"><strong>Composition and
Extensibility</strong> - Modules and phases improve support for
composability and extensibility. Modules support composability and are
able to add support for new WS-* specifications in a simple and clean
manner. They are however, not hot deployable as they change the overall
behavior of the system.</p>
</li>
</ul><p>Axis2/C team is working hard to continuously improve the implementation.
Please note that this is an open-source effort. If you feel you have some
time to spare, please get involved and lend us a hand! The Axis2/C developer
community welcomes your participation and contributions.</p><p>Let us know what you think! Please send your feedback on Axis2/C to "<a href="mailto:axis-user@ws.apache.org">axis-c-user@ws.apache.org</a>" and
please remember to prefix the subject of the mail with [Axis2].</p><p>The following sections will guide on how to write Web service
clients and services.</p><p><a name="Web_Services_Using_Axis2"></a></p></div><div class="subsection"><a name="Web_Services_Using_Axis2_C"></a><h3>Web Services Using Axis2/C</h3><p>Before starting, please make sure that you have installed Axis2/C
correctly and whether you can run the axis2_http_server located in
AXIS2C_HOME/bin (See <a href="installationguide.html">Installation Guide</a>
for details).</p><p><a name="Writing_Web_Services_Using_Axis2_C"></a></p></div><div class="subsection"><a name="Writing_Web_Services_Using_Axis2_C"></a><h3>Writing Web Services Using Axis2/C</h3><p><a id="Creating_Web_Service__MyService_"></a></p></div><div class="subsection"><a name="Creating_Web_Service__Echo_service_"></a><h3>Creating Web Service (Echo service)</h3><p>First let's see how we can write a simple Web Service (echo service) using
Axis2/C's primary interfaces and how to deploy it. For this purpose we will
create a Web Service with one operation as follows.</p>
<div class="source"><pre>
axiom_node_t* axis2_echo_echo(axiom_node_t *echo_node){}
</pre></div>
<p>You can have a peek at the complete source code for this example echo
service located in the "AXIS2C_HOME/samples/server/echo" directory.</p><p><a id="How_to_write_the_Web_Service_"></a></p></div><div class="subsection"><a name="How_to_write_the_Web_Service_"></a><h3>How to write the Web Service?</h3><p>Writing a new Web Service with Axis2/C involves four steps. Let's take echo
service as our example.</p><ol>
<li><p style="margin-bottom: 0in;">Write a echo_skeleton.c file which
implements the API given in axis2_svc_skeleton.h header file.</p>
</li>
<li>Write the service implementation source file (in this case echo.c
service) which implements the actual business logic.</li>
<li>Write a services.xml file to explain the Web service.</li>
<li>Create a folder with the service name under AXIS2C_HOME/services and
put the compiled service ( .dll or .so file) for the Web service and
services.xml file into that folder.</li>
</ol><p><a name="Step1"></a></p></div><div class="subsection"><a name="Step1_:Write_the_echo_skeleton_c_file_implementing_the_axis2_svc_skeleton_h"></a><h3>Step1 :Write the echo_skeleton.c file implementing the axis2_svc_skeleton.h</h3><p>axis2_svc_skeleton.h header file has the axis2_svc_skeleton_ops_t
operations struct which defines four function pointers to be implemented and
assigned by a service skeleton.</p><p>They are:</p>
<div class="source"><pre>
int (AXIS2_CALL * init) (axis2_svc_skeleton_t *svc_skeleton,
const axis2_env_t *env);
axiom_node_t * (AXIS2_CALL* invoke)(axis2_svc_skeleton_t *svc_skeli,
const axis2_env_t *env, axiom_node_t *node);
axiom_node_t *(AXIS2_CALL* on_fault)(axis2_svc_skeleton_t *svc_skeli,
const axis2_env_t *env, axiom_node_t *node);
int (AXIS2_CALL *free)(axis2_svc_skeleton_t *svc_skeli,
const axis2_env_t *env);
</pre></div>
<p>Let's implement the above functions for echo service.</p><p><i><code>/* Initialize the service */</code></i><br></br>
<code>int AXIS2_CALL</code><br></br>
<code>echo_init(axis2_svc_skeleton_t *svc_skeleton,</code><br></br>
<code>                        const axis2_env_t *env)</code><br></br>
<code>{</code><br></br>
<code>    svc_skeleton-&gt;func_array = axis2_array_list_create(env, 0);</code><br></br>
<code>    </code><i><code>/* Add the implemented operation names of the service to  </code><br></br>
<code>     * the array list of functions </code><br></br>
<code>     */</code></i><br></br>
<code>    AXIS2_ARRAY_LIST_ADD(svc_skeleton-&gt;func_array, env, "echoString");</code><br></br>
<code>    </code><i><code>/* Any initialization stuff of echo service should go here */</code></i><br></br>
<code>    </code><b><code>return</code></b><code> AXIS2_SUCCESS;</code><br></br>
<code>}</code><br></br>
<br></br>
<i><code>/*</code><br></br>
<code> * This method invokes the right service method </code><br></br>
<code> */</code></i><br></br>
<code>axiom_node_t* AXIS2_CALL</code><br></br>
<code>echo_invoke(axis2_svc_skeleton_t *svc_skeleton,</code><br></br>
<code>            const axis2_env_t *env,</code><br></br>
<code>            axiom_node_t *node)</code><br></br>
<code>{</code><br></br>
<code>    </code><i><code>/* Invoke the business logic.</code><br></br>
<code>     * Depending on the function name invoke the correct impl method.</code><br></br>
<code>     * We have only echo in this sample, hence invoke echo method.</code><br></br>
<code>     * To see how to deal with multiple impl methods, have a look at the</code><br></br>
<code>     * math sample.</code><br></br>
<code>     */</code></i><br></br>
<code>    </code><b><code>return</code></b><code> axis2_echo_echo(env, node);</code><br></br>
<code>}</code><br></br>
<br></br>
<i><code>/* On fault, handle the fault */</code></i><br></br>
<code>axiom_node_t* AXIS2_CALL</code><br></br>
<code>echo_on_fault(axis2_svc_skeleton_t *svc_skeli, </code><br></br>
<code>              const axis2_env_t *env, axiom_node_t *node)</code><br></br>
<code>{</code><br></br>
<code>   </code><i><code>/* Here we are just setting a simple error message inside an element </code><br></br>
<code>    * called 'EchoServiceError' </code><br></br>
<code>    */</code></i><br></br>
<code>    axiom_node_t *error_node = NULL;</code><br></br>
<code>    axiom_node_t* text_node = NULL;</code><br></br>
<code>    axiom_element_t *error_ele = NULL;</code><br></br>
<code>    error_ele = axiom_element_create(env, node, "EchoServiceError", NULL, </code><br></br>
<code>        &amp;error_node);</code><br></br>
<code>    AXIOM_ELEMENT_SET_TEXT(error_ele, env, "Echo service failed ", </code><br></br>
<code>        text_node);</code><br></br>
<code>    </code><b><code>return</code></b><code> error_node;</code><br></br>
<code>}</code><br></br>
<br></br>
<i><code>/* Free the resources used */</code></i><br></br>
<code>int AXIS2_CALL</code><br></br>
<code>echo_free(axis2_svc_skeleton_t *svc_skeleton,</code><br></br>
<code>            const axis2_env_t *env)</code><br></br>
<code>{</code><br></br>
<code>    </code><i><code>/* Free the function array */</code></i><br></br>
<code>    </code><b><code>if</code></b><code>(svc_skeleton-&gt;func_array)</code><br></br>
<code>    {</code><br></br>
<code>        AXIS2_ARRAY_LIST_FREE(svc_skeleton-&gt;func_array, env);</code><br></br>
<code>        svc_skeleton-&gt;func_array = NULL;</code><br></br>
<code>    }</code><br></br>
<code>    </code><br></br>
<code>    </code><i><code>/* Free the function array */</code></i><br></br>
<code>    </code><b><code>if</code></b><code>(svc_skeleton-&gt;ops)</code><br></br>
<code>    {</code><br></br>
<code>        AXIS2_FREE(env-&gt;allocator, svc_skeleton-&gt;ops);</code><br></br>
<code>        svc_skeleton-&gt;ops = NULL;</code><br></br>
<code>    }</code><br></br>
<code>    </code><br></br>
<code>    </code><i><code>/* Free the service skeleton */</code></i><br></br>
<code>    </code><b><code>if</code></b><code>(svc_skeleton)</code><br></br>
<code>    {</code><br></br>
<code>        AXIS2_FREE(env-&gt;allocator, svc_skeleton);</code><br></br>
<code>        svc_skeleton = NULL;</code><br></br>
<code>    }</code><br></br>
<br></br>
<code>    </code><b><code>return</code></b><code> AXIS2_SUCCESS; </code><br></br>
<code>}</code><br></br>
</p><p></p><p>Now we can write the <code>create</code> function of the
echo_service_skeleton as follows:</p><p><i><code>/*Create function */</code><br></br>
</i><code>axis2_svc_skeleton_t *</code><br></br>
<code>axis2_echo_create(const axis2_env_t *env)</code><br></br>
<code>{</code><br></br>
<code>    axis2_svc_skeleton_t *svc_skeleton = NULL;</code><br></br>
<code>    </code><i><code>/* Allocate memory for the structs */</code></i><br></br>
<code>    svc_skeleton = AXIS2_MALLOC(env-&gt;allocator, </code><br></br>
<code>        </code><b><code>sizeof</code></b><code>(axis2_svc_skeleton_t));</code><br></br>
<br></br>
<code>    svc_skeleton-&gt;ops = AXIS2_MALLOC(</code><br></br>
<code>        env-&gt;allocator, </code><b><code>sizeof</code></b><code>(axis2_svc_skeleton_ops_t));</code><br></br>
<br></br>
<code>    </code><i><code>/* Assign function pointers */</code></i><br></br>
<code>    svc_skeleton-&gt;ops-&gt;free = echo_free;</code><br></br>
<code>    svc_skeleton-&gt;ops-&gt;init = echo_init;</code><br></br>
<code>    svc_skeleton-&gt;ops-&gt;invoke = echo_invoke;</code><br></br>
<code>    svc_skeleton-&gt;ops-&gt;on_fault = echo_on_fault;</code><br></br>
<br></br>
<code>    </code><b><code>return</code></b><code> svc_skeleton;</code><br></br>
<code>}</code></p><p>In addition to the above functions, every service must have the following
two functions with exactly the same function signature as in xxx_skeleton.c
file.</p><p><code>AXIS2_EXPORT int </code><br></br>
<code>axis2_get_instance(axis2_svc_skeleton_t **inst,</code><br></br>
<code>                   const axis2_env_t *env)</code><br></br>
<code>{</code><br></br>
<code>    *inst = axis2_echo_create(env);</code><br></br>
<code>    </code><b><code>if</code></b><code>(!(*inst))</code><br></br>
<code>    {</code><br></br>
<code>        </code><b><code>return</code></b><code> AXIS2_FAILURE;</code><br></br>
<code>    }</code><br></br>
<code>    </code><b><code>return</code></b><code> AXIS2_SUCCESS;</code><br></br>
<code>}</code><br></br>
<br></br>
<code>AXIS2_EXPORT int </code><br></br>
<code>axis2_remove_instance(axis2_svc_skeleton_t *inst,</code><br></br>
<code>                      const axis2_env_t *env)</code><br></br>
<code>{</code><br></br>
<code>    axis2_status_t status = AXIS2_FAILURE;</code><br></br>
<code>    </code><b><code>if</code></b><code> (inst)</code><br></br>
<code>    {</code><br></br>
<code>        status = AXIS2_SVC_SKELETON_FREE(inst, env);</code><br></br>
<code>    }</code><br></br>
<code>    </code><b><code>return</code></b><code> status;</code><br></br>
}<br></br>
</p><p></p><p>Axis2/C engine can load the service dll. However, it needs to know which
method to call. Since C does not have reflection, we need to have some dll
exposing functions known to Axis2/C engine.
<b><code>axis2_get_instance</code></b> and
<b><code>axis2_remove_instance</code></b> are the two functions that need to
be exposed from a service dll (or any other dll of Axis2/C engine). Axis2/C
engine calls <code>axis2_get_instance</code> method, which creates a new
service instance, and casts the return pointer to
<code>axis2_svc_skeleton</code> interface. Then, the interface methods can be
called by Axis2/C engine.</p><p><a name="Step2"></a></p></div><div class="subsection"><a name="Step2_:_Now_we_can_write_the_echo_service_in_a_file_echo_c"></a><h3>Step2 : Now we can write the echo service in a file echo.c</h3><p><code>axiom_node_t *</code><br></br>
<code>axis2_echo_echo (const axis2_env_t *env, axiom_node_t *node)</code><br></br>
<code>{</code><br></br>
<code>    axiom_node_t *text_parent_node = NULL;</code><br></br>
<code>    axiom_node_t *text_node = NULL;</code><br></br>
<code>    axiom_node_t *ret_node = NULL;</code><br></br>
<br></br>
<code>    AXIS2_ENV_CHECK(env, NULL);</code><br></br>
<code>   </code><br></br>
<code>    </code><i><code>/* Expected request format is :-</code><br></br>
<code>     * &lt;ns1:echoString xmlns:ns1="http://localhost:9090/axis2/services/echo"&gt;</code><br></br>
<code>     *      &lt;text&gt;echo5&lt;/text&gt;</code><br></br>
<code>     * &lt;/ns1:echoString&gt;</code><br></br>
<code>     */</code></i><br></br>
<code>    </code><b><code>if</code></b><code> (!node) </code><i><code>/* 'echoString' node */</code></i><br></br>
<code>    {</code><br></br>
<code>        AXIS2_ERROR_SET(env-&gt;error, AXIS2_ERROR_SVC_SKEL_INPUT_OM_NODE_NULL, AXIS2_FAILURE);</code><br></br>
<code>        printf("Echo client ERROR: input parameter NULL\n");</code><br></br>
<code>        </code><b><code>return</code></b><code> NULL;</code><br></br>
<code>    }</code><br></br>
<br></br>
<code>    text_parent_node = AXIOM_NODE_GET_FIRST_CHILD(node, env);</code><br></br>
<code>    </code><b><code>if</code></b><code> (!text_parent_node) </code><i><code>/* 'text' node */</code></i><br></br>
<code>    {</code><br></br>
<code>        AXIS2_ERROR_SET(env-&gt;error, AXIS2_ERROR_SVC_SKEL_INVALID_XML_FORMAT_IN_REQUEST, AXIS2_FAILURE);</code><br></br>
<code>        printf("Echo client ERROR: invalid XML in request\n");</code><br></br>
<code>        </code><b><code>return</code></b><code> NULL;</code><br></br>
<code>    }</code><br></br>
<code>    </code><br></br>
<code>    text_node = AXIOM_NODE_GET_FIRST_CHILD(text_parent_node, env);</code><br></br>
<code>    </code><b><code>if</code></b><code> (!text_node) </code><i><code>/* actual text to echo */</code></i><br></br>
<code>    {</code><br></br>
<code>        AXIS2_ERROR_SET(env-&gt;error, AXIS2_ERROR_SVC_SKEL_INVALID_XML_FORMAT_IN_REQUEST, AXIS2_FAILURE);</code><br></br>
<code>        printf("Echo client ERROR: invalid XML in request\n");</code><br></br>
<code>        </code><b><code>return</code></b><code> NULL;</code><br></br>
<code>    }</code><br></br>
<code>    </code><br></br>
<code>    </code><b><code>if</code></b><code> (AXIOM_NODE_GET_NODE_TYPE(text_node, env) == AXIOM_TEXT)</code><br></br>
<code>    {</code><br></br>
<code>        axiom_text_t *text = (axiom_text_t *)AXIOM_NODE_GET_DATA_ELEMENT(text_node, env);</code><br></br>
<code>        </code><b><code>if</code></b><code>( text &amp;&amp; AXIOM_TEXT_GET_VALUE(text , env))</code><br></br>
<code>        {</code><br></br>
<code>            axis2_char_t *text_str = AXIOM_TEXT_GET_VALUE(text, env);</code><br></br>
<code>            printf("Echoing text value  %s \n", text_str);</code><br></br>
<code>            ret_node = build_om_programatically(env, text_str);</code><br></br>
<code>        }</code><br></br>
<code>    }</code><br></br>
<code>    </code><b><code>else</code></b><br></br>
<code>    {</code><br></br>
<code>        AXIS2_ERROR_SET(env-&gt;error, AXIS2_ERROR_SVC_SKEL_INVALID_XML_FORMAT_IN_REQUEST, AXIS2_FAILURE);</code><br></br>
<code>        printf("Echo client ERROR: invalid XML in request\n");</code><br></br>
<code>        </code><b><code>return</code></b><code> NULL;</code><br></br>
<code>    }</code><br></br>
<code>        </code><br></br>
<code>    </code><b><code>return</code></b><code> ret_node;</code><br></br>
<code>}</code><br></br>
<br></br>
<i><code>/* Builds the response content */</code></i><br></br>
<code>axiom_node_t *</code><br></br>
<code>build_om_programatically(const
axis2_env_t *env, axis2_char_t *text)</code><br></br>
<code>{</code><br></br>
<code>    axiom_node_t *echo_om_node = NULL;</code><br></br>
<code>    axiom_element_t* echo_om_ele = NULL;</code><br></br>
<code>    axiom_node_t* text_om_node = NULL;</code><br></br>
<code>    axiom_element_t * text_om_ele = NULL;</code><br></br>
<code>    axiom_namespace_t *ns1 = NULL;</code><br></br>
<code>    </code><br></br>
<code>    ns1 = axiom_namespace_create (env, "http://localhost:9090/axis2/services/echo", "ns1");</code><br></br>
<br></br>
<code>    echo_om_ele = axiom_element_create(env, NULL, "echoString", ns1, &amp;echo_om_node);</code><br></br>
<code>    </code><br></br>
<code>    text_om_ele = axiom_element_create(env, echo_om_node, "text", NULL, &amp;text_om_node);</code><br></br>
<br></br>
<code>    AXIOM_ELEMENT_SET_TEXT(text_om_ele, env, text, text_om_node);</code><br></br>
<code>    </code><br></br>
<code>    </code><b><code>return</code></b><code> echo_om_node;</code><br></br>
<code>}</code><br></br>
</p><p><a name="Step3"></a></p></div><div class="subsection"><a name="Step3_:Write_the_services_xml_file"></a><h3>Step3 :Write the services.xml file</h3><p>Axis2/C uses "services.xml" file to keep configurations of a Web service.
Each Web service deployed in Axis2/C needs a "services.xml" file containing
the configurations. Note that services.xml has the same semantics as Axis2
Java's services.xml file. Only difference is that instead of giving package
qualified class name, we use the dll name for class attributes.</p><p>"services.xml" for echo will be as follows:</p><code class="code">&lt;service name="echo"&gt;<br></br> &lt;parameter name="ServiceClass" locked="xsd:false"&gt;echo&lt;/parameter&gt;<br></br> &lt;description&gt;<br></br> This is a echo service<br></br> &lt;/description&gt;<br></br><br></br> &lt;operation name="echoString"&gt;<br></br> &lt;parameter name="wsamapping"&gt;<br></br> http://localhost:9090/axis2/services/echo/echoString<br></br> &lt;/parameter&gt;<br></br> &lt;/operation&gt;<br></br>&lt;/service&gt;</code><p>Name of the service will be the name of the folder with the shared library
and services.xml. In this example we will have a folder named
"echo" in which we have the echo.dll (or libecho.so on Linux platform) and
services.xml file.</p><p>You can write a services.xml file to include a group of services instead
of a single service. This makes 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 <code>axis2_svc_grp_ctx</code>
(Service Group Context ). If you hope to use this functionality, the
services.xml file should have following format:<br></br>
</p><code class="code">&lt;serviceGroup&gt;<br></br> &lt;service name="Service1"&gt;<br></br> &lt;!-- details for Service1 --&gt;<br></br> &lt;/service&gt;<br></br> &lt;service name="Service2"&gt;<br></br> &lt;!-- details for Service2 --&gt;<br></br> &lt;/service&gt;<br></br> &lt;module ref="ModuleName" /&gt;<br></br> &lt;parameter name="serviceGroupParam1" locked="false"&gt;value 1&lt;/parameter&gt;<br></br>&lt;/serviceGroup&gt;</code><p><strong>Note :</strong> Name of the service is a compulsory attribute</p><p><a name="Step4"></a></p></div><div class="subsection"><a name="Step4_:Create_the_Web_service_folder_in_services_folder_of_the_repository_"></a><h3>Step4 :Create the Web service folder in services folder of the repository.</h3><p>In Axis2/C , it is required to create a folder with the corresponding
service/service group name which will contain the shared library (compiled
service) and the services.xml file which describes the Web service. So for
this example, we will have to create a folder named "echo", which contains
the services.xml file and echo dll.</p><p><a name="Step5"></a></p></div><div class="subsection"><a name="Step5_:Archive_Based_Deployment_Model"></a><h3>Step5 :Archive Based Deployment Model</h3><p>Axis2 uses ".aar" (Axis Archive) file as the deployment package for the
Web services. Therefore, for echo service we will use "echo.aar". Note that
the name of the service will be the name of the archive file. To create
"echo.aar" user can create a zip file containing echo.so and services.xml and
rename the zip extension to aar. Then Axis2 understands it as a service
archive.</p><p><a name="Writing_Web_Services_Using_Code_Generator"></a></p></div><div class="subsection"><a name="Writing_Web_Services_Skeleton_Using_Code_Generator"></a><h3>Writing Web Services Skeleton Using Code Generator</h3><p><a id="WSDL2C_tool"></a></p></div><div class="subsection"><a name="WSDL2C_tool"></a><h3>WSDL2C tool</h3><p>Axis2/Java WSDL2C tool supports generation of Axis2/C stub and
skeleton. <a href="http://svn.apache.org/viewvc/webservices/axis2/trunk/java" class="externalLink" title="External Link">Axis2/Java
SVN</a> revision 414253 and later versions provide this facility. A basic
guide for the tool can be found <a href="http://ws.apache.org/axis2/1_0/userguide2.html#Writing_Web_Services_by_Code_Generating_Skeleton" class="externalLink" title="External Link">here.</a></p><p>We will run the tool with the following parameters and generate the
skeleton and other required files to support ADB (Axis Data Binding). In
order to run the tool, <span style="font-weight: bold;">set all the .jar
library files in the Axis2/Java to the classpath</span>. To generate code
with no data binding support, just replace -d adb -u with -d none</p>
<div class="source"><pre>
java org.apache.axis2.wsdl.WSDL2C -uri interoptestdoclitparameters.wsdl -ss -sd -d adb -u
</pre></div>
<p>If you need an XML in/out programming model, you can just ignore the data
binding support by setting the following parameters.
<pre>java org.apache.axis2.wsdl.WSDL2C -uri interoptestdoclitparameters.wsdl -ss -sd -d none</pre>
</p><p>The WSDL <code>interoptestdoclitparameters.wsdl</code> can be found in
&lt;axis2_src_dir&gt;/test/resources directory. This is used to generate stub
and skeleton code throughout this User's Guide.</p><p><a id="Implement_the_Business_Logic"></a></p></div><div class="subsection"><a name="Implement_the_Business_Logic"></a><h3>Implement the Business Logic</h3><p>
Locate the skeleton source file from the generated files:
"<code>axis2_WSDLInteropTestDocLitService.c</code>". You can go through the
rest of the guide to add the business logic to the following operations in
the WSDL.
<ul>
<li>echoString - Operation that echoes a String value.</li>
<li>echoStringArray - Operation that accepts a string array as the input and
echoes them back.</li>
<li>echoStruct - Operation that accepts a Struct as the input and echoes
them back.</li>
</ul></p><p>Complete skeleton source file for the above operations can be found under
&lt;axis2_src_dir&gt;/samples/codegen/server/interop_doc2 directory with the
name "<code>axis2_WSDLInteropTestDocLitService.c</code>".</p><p><a id="echoString"></a></p></div><div class="subsection"><a name="echoString"></a><h3>echoString</h3><p>If you generate the code with data binding support, you will find the
following code segment in the
"<code>axis2_WSDLInteropTestDocLitService.c</code>". Fill the business logic
inside this function as shown below:</p>
<div class="source"><pre>
axis2_echoStringResponse_t*
axis2_WSDLInteropTestDocLitService_echoString
(const axis2_env_t* env ,axis2_echoString_t* param6 )
{
/* Todo fill this with the necessary business logic *}
</pre></div>
<p>Once the business logic is filled, it will be as follows. The code is
simple and the inline comments provide explanation.</p>
<div class="source"><pre>
axis2_echoStringResponse_t*
axis2_WSDLInteropTestDocLitService_echoString
(const axis2_env_t* env ,axis2_echoString_t* param6 )
{
axis2_echoString_t* echo_in = param6;
axis2_echoStringResponse_t* echo_out = NULL;
char* echo_string = NULL;
/* retrieve the string input */
echo_string = AXIS2_ECHOSTRING_GET_PARAM0 ( echo_in, env );
/* create the response and set the output string */
echo_out = axis2_echoStringResponse_create ( env );
AXIS2_ECHOSTRUCTRESPONSE_SET_RETURN ( echo_out, env, echo_string );
return echo_out;
}
</pre></div>
</div><div class="subsection"><a name="echoStringArray"></a><h3>echoStringArray</h3>
<div class="source"><pre>
axis2_echoStringArrayResponse_t*
axis2_WSDLInteropTestDocLitService_echoStringArray
(const axis2_env_t* env ,axis2_echoStringArray_t* param2 )
{
axis2_echoStringArray_t* echo_in = param2;
axis2_echoStringArrayResponse_t* echo_out = NULL;
axis2_ArrayOfstring_literal_t* array_in = NULL;
axis2_ArrayOfstring_literal_t* array_out = NULL;
char ** string_array = NULL;
int string_array_length = 0;
/* retrieve the array from input*/
array_in = AXIS2_ECHOSTRINGARRAY_GET_PARAM0( echo_in, env);
/* retrieve the string_array and array length */
string_array =
AXIS2_ARRAYOFSTRING_LITERAL_GET_STRING
(array_in, env,&amp;string_array_length );
/* create the output array and set the string array and length */
array_out = axis2_ArrayOfstring_literal_create ( env );
AXIS2_ARRAYOFSTRING_LITERAL_SET_STRING(
array_out, env, string_array, string_array_length );
/* create the response and set the output*/
echo_out = axis2_echoStringArrayResponse_create ( env );
AXIS2_ECHOSTRINGARRAYRESPONSE_SET_RETURN ( echo_out, env , array_out
);
return echo_out;
</pre></div>
</div><div class="subsection"><a name="echoStruct"></a><h3>echoStruct</h3>
<div class="source"><pre>
axis2_echoStructResponse_t*
axis2_WSDLInteropTestDocLitService_echoStruct
(const axis2_env_t* env ,axis2_echoStruct_t* param4 )
{
axis2_echoStruct_t* echo_in = param4;
axis2_echoStructResponse_t* echo_out = NULL;
axis2_SOAPStruct_t* struct_in = NULL;
axis2_SOAPStruct_t* struct_out = NULL;
float float_val = 0;
int int_val = 0;
char* string_val = NULL;
/* retrieve the structure from input */
struct_in = AXIS2_ECHOSTRUCT_GET_PARAM0( echo_in, env);
/* retrieve each value from the structure */
float_val = AXIS2_SOAPSTRUCT_GET_VARFLOAT ( struct_in, env);
int_val = AXIS2_SOAPSTRUCT_GET_VARINT ( struct_in, env);
string_val = AXIS2_SOAPSTRUCT_GET_VARSTRING ( struct_in, env);
/* create the output structure and set values */
struct_out = axis2_SOAPStruct_create( env );
AXIS2_SOAPSTRUCT_SET_VARFLOAT ( struct_out, env, float_val );
AXIS2_SOAPSTRUCT_SET_VARINT ( struct_out, env, int_val );
AXIS2_SOAPSTRUCT_SET_VARSTRING ( struct_out, env, string_val );
/* create the response and set the output structure*/
echo_out = axis2_echoStructResponse_create ( env );
AXIS2_ECHOSTRUCTRESPONSE_SET_RETURN ( echo_out, env, struct_out );
return echo_out;
</pre></div>
</div><div class="subsection"><a name="services_xml"></a><h3>services.xml</h3><p>
Axis2 uses "services.xml" to hold the configurations for a particular Web
service deployed in the Axis2 engine. When we generate the skeleton using the
WSDL2Java tool, it will generate the required services.xml for this Web
service as well. This is essential to <a href="#deploy">deploy the
service</a>. Please refer to the '<a href="#Step3">Write the
services.xml</a>' section in this guide to learn more about services.xml.
<a name="deploy"></a></p></div><div class="subsection"><a name="Deploy_the_Web_Service"></a><h3>Deploy the Web Service</h3><p>We simply put our service folder or the ".aar" file to the services
directory. You need restart the server for the engine to pick this
service.</p><p><a name="Web_Service_Clients_Using_Axis2"></a></p></div><div class="subsection"><a name="Web_Service_Clients_Using_Axis2_C"></a><h3>Web Service Clients Using Axis2/C</h3><p>Now let's see how we can write a Web service client to consume a Web
service.</p><p>Web services can be used to provide wide range of functionality to the
users ranging from simple, less time consuming  operations such as
"getStockQuote"  to time consuming business services. When we utilize (invoke
using client applications) these Web services, we cannot use some simple
generic invocation paradigm that suits 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 which takes
a long time to complete, then most of the time 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 consequences such as One-Way transports
that come into play when we need them. Let's try to analyze some common
service invocation paradigms.</p><p>Many Web service engines provide the users with a Blocking and
Non-Blocking client APIs.</p><ul>
<li><p style="margin-bottom: 0in;"><b>Blocking API</b> -Once the service
invocation is called, the client application hangs and only gets control
back when the operation completes, after which client receives a response
or a fault. This is the simplest way of invoking Web services and it also
suits many business situations.</p>
</li>
<li><b>Non-Blocking API</b>- This is a callback or polling based API.
Hence, once a service invocation is called, the client application
immediately gets the control back and the response is retrieved using the
callback object provided. This approach provides the client application
with the flexibility to invoke several Web services simultaneously without
blocking the operation that has already been invoked.</li>
</ul><p>Both these mechanisms work in the API level. Let's name the asynchronous
behavior that we can get using the <strong>Non-Blocking API</strong> as
<b>API Level Asynchrony.</b></p><p>Both these mechanisms use single transport connection to send the request
and to receive the response. They severely lack the capability of using two
transport connections for the request and the response (either One-Way of
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 <strong>two
separate transport connections for request and response</strong>. The
asynchronous behavior that we gain using this solution can be called
<b>Transport Level Asynchrony</b>.</p><p>By combining API Level Asynchrony &amp; Transport Level Asynchrony we can
obtain four different invocation patterns for Web services as shown in the
following table.</p><p></p><table class="bodyTable"><tbody>
<tr class="a"><td><strong>API (Blocking/Non-Blocking)</strong></td><td><strong> Dual Transports (Yes/No)</strong></td><td><strong>Description</strong></td></tr>
<tr class="b"><td>Blocking</td><td>No</td><td>Simplest and the familiar invocation pattern</td></tr>
<tr class="a"><td>Non-Blocking</td><td>No</td><td>Using callbacks or polling</td></tr>
<tr class="b"><td>Blocking</td><td>Yes</td><td>This is useful when the service operation is IN-OUT in nature but
the transport used is One-Way (e.g. SMTP)</td></tr>
<tr class="a"><td>Non-Blocking</td><td>Yes</td><td>This can be used to gain the maximum asynchronous behavior. No
blocking in the API level and also in the transport level</td></tr>
</tbody></table><p>Axis2/C provides the user with all these possibilities to invoke Web
services.</p><p>Below we describe how to write Web Services Clients using Axis2/C.</p><p><a name="Writing_Web_Service_Clients_using_Axis2%27s_Primary_APIs"></a></p></div><div class="subsection"><a name="Writing_Web_Service_Clients_Using_Axis2_s_Primary_APIs"></a><h3>Writing Web Service Clients Using Axis2's Primary APIs</h3><p><a id="EchoBlockingClient"></a></p></div><div class="subsection"><a name="echo_blocking_Client"></a><h3>echo_blocking Client</h3><p>Axis2/C provides the user with several invocation patterns for Web
Services, ranging from pure blocking single channel invocations to a
non-blocking dual channel invocation. Let's first see how we can write a
client to invoke "echo" operation of "echo" service using the simplest
blocking invocation. The client code you need to write is as follows.</p>
<div class="source"><pre>
/* Create EPR with given address */
endpoint_ref = axis2_endpoint_ref_create(env, address);
/* Setup options */
options = axis2_options_create(env);
AXIS2_OPTIONS_SET_TO(options, env, endpoint_ref);
/* Set the deploy folder */
client_home = AXIS2_GETENV("AXIS2C_HOME");
if (!client_home)
client_home = "../../deploy";
/* Create service client */
svc_client = axis2_svc_client_create(env, client_home);
if (!svc_client)
{
printf("Error creating service client\n");
AXIS2_LOG_ERROR(env-&gt;log, AXIS2_LOG_SI, "Stub invoke FAILED:
Error code:
% d :: %s", env-&gt;error-&gt;error_number,
AXIS2_ERROR_GET_MESSAGE(env-&gt;error));
}
/* Set service client options */
AXIS2_SVC_CLIENT_SET_OPTIONS(svc_client, env, options); /* Build the
SOAP request message payload using OM API.*/
payload = build_om_payload_for_echo_svc(env);
/* Send request */
ret_node = AXIS2_SVC_CLIENT_SEND_RECEIVE(svc_client, env, payload);
/* Print result */
if(ret_node)
{
axis2_char_t *om_str = NULL;
om_str = AXIOM_NODE_TO_STRING(ret_node, env);
if (om_str)
printf("\nReceived OM : %s\n", om_str);
printf("\necho client invoke SUCCESSFUL!\n");
}
else
{
AXIS2_LOG_ERROR(env-&gt;log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:"
" %d :: %s", env-&gt;error-&gt;error_number,
AXIS2_ERROR_GET_MESSAGE(env-&gt;error));
printf("echo client invoke FAILED!\n");
}
</pre></div>
<p>The comments in the above code explains the code. In simple terms, these
are the steps:</p><ol>
<li>Set up the options to be used in the invocation.</li>
<li>Create the service client.</li>
<li>Set the options to service client.</li>
<li>Build the XML payload to be sent out using AXIOM.</li>
<li>Send payload and receive result XML as OM.</li>
<li>Consume result.</li>
</ol><p>Options can be used to define the invocation parameters such as target
endpoint, soap version, addressing parameters, etc. When creating service
client, the deployment folder has to be passed as a parameter. It is from the
deploy folder, the configuration is picked up, using the axis2.xml file. The
send_receive function of the service client sends the XML given as a payload
to the server side and returns the result received. Basically this is the XML
in/out model. Once the result is received, the user can consume the result in
whichever the way(s) he wishes.</p><p><a id="EchoNonBlockingClient"></a></p></div><div class="subsection"><a name="echo_non_blocking_Client"></a><h3>echo_non_blocking Client</h3><p>In the echo_blocking client once the "send_receive" function is called,
the client is blocked till the operation is completed. 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/C provides a callback based non-blocking
API for users.</p><p>A sample client for this can be found under
"&lt;axis2c_home&gt;/samples/user_guide/clients" with the name
echo_non_blocking.c. The changes that user may have to do with respect to the
"echo_blocking" client in order to make it non-blocking, would be as
follows:</p>
<div class="source"><pre>AXIS2_SVC_CLIENT_SEND_RECEIVE_NON_BLOCKING(svc_client, env, payload, callback);
</pre></div>
<p>Unlike "send_receive", "send_receive_non_blocking" accepts a callback
struct in addition to payload. Axis2/C client API provides a callback struct
with the following associated functions:</p>
<div class="source"><pre>
axis2_status_t (AXIS2_CALL *
on_complete)(
struct axis2_callback *callback,
const axis2_env_t *env);
axis2_status_t (AXIS2_CALL *
on_error)(
struct axis2_callback *callback,
const axis2_env_t *env,
int exception);
axis2_bool_t (AXIS2_CALL *
get_complete)(
struct axis2_callback *callback,
const axis2_env_t *env);
</pre></div>
<p>The user is expected to implement the "on_complete " and "on_error "
functions and set them on the callback using the "set_on_complete" and
"set_on_error" API calls. In the sample, ''on complete'' is implemented by
"echo_callback_on_complete" function and is set on the callback struct
created as shown below:</p>
<div class="source"><pre>AXIS2_CALLBACK_SET_ON_COMPLETE(callback, echo_callback_on_complete);
</pre></div>
<p>Axis2/C engine calls the "on_complete" method once the Web service
response is received by the Axis2/C client API (that is service_client). This
will eliminate the blocking nature of the Web service invocations and
provide the user with the flexibility to use non-blocking API for Web
service clients.</p><p>Please have a look at the echo_non_blocking.c file located at
"&lt;axis2c_home&gt;/samples/user_guide/client" for more details.</p><p><a id="EchoNonBlockingDualClient"></a></p></div><div class="subsection"><a name="echo_non_blocking_dual_Client"></a><h3>echo_non_blocking_dual Client</h3><p>The solution provided by the non-blocking API has one limitation when it
comes to  Web service invocations,it takes a long time to complete. The
limitation is due to the use of a single transport connection to invoke the
Web service and to retrieve the response. In other words, client API provides
a non blocking invocation mechanism for the users, but the request and the
response comes 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.</p><p>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).
<a href="http://www.w3.org/2002/ws/addr/" class="externalLink" title="External Link">WS-Addressing</a> provides a neat
solution to this using &lt;wsa:MessageID&gt; and &lt;wsa:RelatesTo&gt;
headers. Axis2/C provides support for addressing based correlation mechanism
and a compliant client API to invoke Web services with two transport
connections.</p><p>Users can select between blocking or 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. All you have to do is to set
"use_separate_listener" to true in options:</p>
<div class="source"><pre>AXIS2_OPTIONS_SET_USE_SEPERATE_LISTENER(options, env, AXIS2_TRUE);
</pre></div>
<p>In addition to setting the use_separate_listener to true, to use dual
transports one has to"engage" the addressing module.</p></div><div class="subsection"><a name="Engaging_Addressing_on_Server_Side"></a><h3>Engaging Addressing on Server Side</h3><p>To engage the addressing module simply add a module reference for
addressing in the "axis2.xml" configuration file. This can be done by adding
the following line to "axis2.xml" file in the deployment folder.</p>
<div class="source"><pre> &lt;module ref="addressing"/&gt;
</pre></div>
<p><strong>Note:</strong> Once you modify the "axis2.xml" file you have to restart the server.
You also have to have the addressing module installed in the modules folder
of the deployment folder. This is done by default when you make the
installation.</p></div><div class="subsection"><a name="Engaging_Addressing_on_Client_Side"></a><h3>Engaging Addressing on Client Side</h3><p>There are two ways of doing this:</p><ol>
<li>Engage addressing globally. This can be done by following the same
steps as done in the case of the server side; add module reference to
axis2.xml and have the module installed in the modules folder of the
deploy folder.</li>
<li>Engage the module on service client using the service_client API.
<pre>AXIS2_SVC_CLIENT_ENGAGE_MODULE(svc_client, env, AXIS2_MODULE_ADDRESSING);</pre>
</li>
</ol><p>Once addressing is engaged, echo_non_blocking_dual client would work
perfectly. Note that by default, Axis2/C comes with addressing enabled
globally.</p><p><a id="EchoBlockingDualClient"></a></p></div><div class="subsection"><a name="echo_blocking_dual_Client"></a><h3>echo_blocking_dual Client</h3><p>This is again a Two-Way transport request/response client, but this time,
we use a Blocking API in the client code. Sample code for this can be found
in the "&lt;axis2c_home&gt;/samples/user_guide/clients/" directory and the
explanation is similar to the <a href="#EchoNonBlockingDualClient">echo_non_blocking_dual client</a>, except
that here we do not use a callback object to handle response. This is an extremely
useful mechanism when the service invocation is IN-OUT in nature and the
transports are One-Way (e.g. SMTP). For the sample client we use two HTTP
connections for request and response.</p><p><a id="Writing_Web_Clients_Using_Code_Generator"></a></p></div><div class="subsection"><a name="Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support"></a><h3>Writing Web Service Clients using Code Generation with Data Binding Support</h3><p>Axis2 code generator provides the data binding support for Web service
client generation as well. You can generate the required stubs from a given
WSDL with the other supporting files. Use the following parameters to
generate the Axis2/C stub code with data binding support. You should have
<a href="http://svn.apache.org/viewvc/webservices/axis2/trunk/java" class="externalLink" title="External Link">Axis2/Java
source SVN</a> revision 414253 or later to generate Axis2/C code.</p>
<div class="source"><pre>java WSDL2C -uri interoptestdoclitparameters.wsdl -d adb -u
</pre></div>
<p>In order to ignore the data binding support (to use XML in/out model),
just use the following parameters.</p>
<div class="source"><pre>java WSDL2C -uri interoptestdoclitparameters.wsdl -d none
</pre></div>
<p>The following section demonstrates how to use the generated code using the
wsdl file "interoptestdoclitparameters.wsdl" to implement the client business
logic.</p><p><a id="Codegenerator_Client_echoString"></a></p></div><div class="subsection"><a name="Client_for_echoString_operation"></a><h3>Client for echoString operation</h3>
<div class="source"><pre>#include "axis2_WSDLInteropTestDocLitService_stub.h"
/*
* demonstrates how to execute the service using databinding */
void invoke_service_using_databinding ( axis2_stub_t* stub,
const axis2_env_t* env );
int main(int argc, char** argv)
{
/* variables to keep the environment */
axis2_env_t* env = NULL;
axis2_char_t* client_home = NULL;
axis2_char_t* endpoint_uri =NULL;
axis2_stub_t* stub= NULL;
/* endpoint uri: if it is NULL endpoint will be picked from the WSDL */
endpoint_uri =
"http://localhost:9090/axis2/services/WSDLInteropTestDocLitService";
env = axis2_env_create_all( "codegen_utest_blocking.log",
AXIS2_LOG_LEVEL_TRACE);
/* Set up deploy folder.*/
client_home = AXIS2_GETENV("AXIS2C_HOME");
if (!client_home)
client_home = "../../../deploy";
/* create the stub using generated code */
stub = axis2_WSDLInteropTestDocLitService_stub_create( env,
client_home , endpoint_uri);
/* calls the service*/
invoke_service_using_databinding ( stub, env );
return 0;
}
void invoke_service_using_databinding ( axis2_stub_t* stub,
const axis2_env_t* env )
{
/* variables used by databinding */
axis2_echoString_t* echo_in = NULL;
axis2_echoStringResponse_t* echo_out = NULL;
/* variables to store data */
char* echo_str = "hello";
char* return_echo_str = NULL;
/* create the input params using databinding */
echo_in = axis2_echoString_create( env );
AXIS2_ECHOSTRING_SET_PARAM0( echo_in, env, echo_str );
/* invoke the web service method*/
echo_out = axis2_echoString( stub, env, echo_in );
/* return the output params using databinding */
return_echo_str = AXIS2_ECHOSTRUCTRESPONSE_GET_RETURN( echo_out, env
);
/* print the result */
printf ( "returned string %s\n", return_echo_str );
}
</pre></div>
<p><a id="Codegenerator_Client_echoStringArray"></a></p></div><div class="subsection"><a name="Client_for_echoStringArray_operation"></a><h3>Client for echoStringArray operation</h3><p>
You can change the <code>invoke_service_using_databinding</code> function to
invoke the echoStringArray operation as follows.
<div class="source"><pre>void invoke_service_using_databinding ( axis2_stub_t* stub, const
axis2_env_t* env )
{
/* variables used by databinding */
axis2_echoStringArray_t* echo_in = NULL;
axis2_echoStringArrayResponse_t* echo_out = NULL;
axis2_ArrayOfstring_literal_t* array_in = NULL;
axis2_ArrayOfstring_literal_t* array_out = NULL;
/* variables to store data */
char *string_array[]= { "test","this","array" };
int array_length = 3;
char **string_return_string_array = NULL;
int return_array_length = 0;
int i = 0;
/*create the input array and set the string array and length*/
array_in = axis2_ArrayOfstring_literal_create (env );
AXIS2_ARRAYOFSTRING_LITERAL_SET_STRING( array_in, env,
string_array, array_length );
/* create the request and set the inputs */
echo_in = axis2_echoStringArray_create ( env );
AXIS2_ECHOSTRINGARRAY_SET_PARAM0( echo_in, env, array_in );
/* invoke the web service method*/
echo_out = axis2_echoStringArray( stub, env, echo_in );
/* return the output params using databinding */
array_out = AXIS2_ECHOSTRINGARRAYRESPONSE_GET_RETURN( echo_out, env
);
/* retrieve the string array values and length */
string_return_string_array = AXIS2_ARRAYOFSTRING_LITERAL_GET_STRING
( array_out, env, &amp;return_array_length );
/* print the output */
for ( i = 0; i &lt; return_array_length ; i ++ )
{
printf("value%d: %s \n", i, string_return_string_array[i] );
}
</pre></div>
<a id="Codegenerator_Client_echoStruct"></a></p></div><div class="subsection"><a name="Client_for_echoStruct_operation"></a><h3>Client for echoStruct operation</h3>
<div class="source"><pre>void invoke_service_using_databinding ( axis2_stub_t* stub,
const axis2_env_t* env )
{
/* variables used by databinding */
axis2_echoStruct_t* echo_in = NULL;
axis2_echoStructResponse_t* echo_out = NULL;
axis2_SOAPStruct_t* struct_in = NULL;
axis2_SOAPStruct_t* struct_out = NULL;
/* variables to store data */
float float_val = 11;
int int_val = 10;
char* string_val = "hello struct";
int ret_int_val = 0;
float ret_float_val = 0;
char* ret_string_val = "";
/* create the struct and set input values*/
struct_in = axis2_SOAPStruct_create( env );
AXIS2_SOAPSTRUCT_SET_VARFLOAT ( struct_in, env, float_val );
AXIS2_SOAPSTRUCT_SET_VARINT ( struct_in, env, int_val );
AXIS2_SOAPSTRUCT_SET_VARSTRING ( struct_in, env, string_val );
/* create the request and set the struct */
echo_in = axis2_echoStruct_create( env );
AXIS2_ECHOSTRUCT_SET_PARAM0( echo_in, env, struct_in );
/* invoke the web service method */
echo_out = axis2_echoStruct( stub, env, echo_in );
/* retrieve the structure from response */
struct_out = AXIS2_ECHOSTRUCTRESPONSE_GET_RETURN( echo_out, env );
/* retrieve each value from the structure */
ret_float_val = AXIS2_SOAPSTRUCT_GET_VARFLOAT ( struct_out, env );
ret_int_val = AXIS2_SOAPSTRUCT_GET_VARINT ( struct_out, env );
ret_string_val = AXIS2_SOAPSTRUCT_GET_VARSTRING ( struct_out, env );
/* print the values */
printf ( "returned values \n");
printf (" float %f\n", ret_float_val );
printf (" int %d \n", ret_int_val );
printf (" string %s \n", ret_string_val);
}
</pre></div>
<p><a id="Providing_security_using_Rampart"></a></p></div><div class="subsection"><a name="Providing_Security_using_Rampart_C"></a><h3>Providing Security using Rampart/C</h3><p>Rampart/C is the security module for Axis2/C, which supports UsernameToken
based authentication and Timestamps as per WS-Security specification. In this
User's Guide we will explain how to use Rampart inside Axis2/C.</p><p><a id="Engaging_rampart_module"></a></p></div><div class="subsection"><a name="Engaging_rampart_module"></a><h3>Engaging rampart module</h3><ul>
<li><b>Step 1:</b> Copy rampart directory created in
AXIS2C_HOME/deploy/rampart to AXIS2C_HOME/deploy/modules
<pre>cp $AXIS2C_HOME/deploy/rampart/rampart $AXIS2C_HOME/deploy/modules</pre>
</li>
<li><b>Step 2:</b>Add following line to the axis2.xml under axisconfig.
This will engage the rampart module.
<pre>&lt;module ref="rampart"/&gt;</pre>
</li>
<li><b>Step 3:</b>Then add the following to axis2.xml file to specify
In/Out flow parameters. You may find a sample axis2.xml file in
rampart/samples/client/echo/data/
<p> &lt;parameter name="OutflowSecurity"&gt;&lt;action&gt;<br></br> &lt;items&gt;UsernameToken Timestamp&lt;/items&gt;<br></br> &lt;user&gt;Gajaba&lt;/user&gt;<br></br> &lt;passwordType&gt;passwordDigest&lt;/passwordType&gt;<br></br> &lt;passwordCallbackClass&gt;/home/gajaba/axis2/c/deploy/rampart/samples/callback/libpwcb.so&lt;/passwordCallbackClass&gt;<br></br> &lt;timeToLive&gt;360&lt;/timeToLive&gt;<br></br> &lt;/action&gt;<br></br> &lt;/parameter&gt;<br></br> </p>
<p class="code"> &lt;parameter name="InflowSecurity"&gt;<br></br>
&lt;action&gt;<br></br> &lt;items&gt;UsernameToken
Timestamp&lt;/items&gt;<br></br>
&lt;passwordCallbackClass&gt;/home/gajaba/axis2/c/deploy/rampart/samples/callback/libpwcb.so&lt;/passwordCallbackClass&gt;<br></br> &lt;/action&gt;<br></br> &lt;/parameter&gt;<br></br> </p>
</li>
</ul><p><strong>Note:</strong> You must replace the value of
<code>passwordCallbackClass</code> parameter to suit your settings.</p><p>Now everything is setup to try out the sample. Start axis2 server and run
the sample under rampart/samples/client/echo. If everything works fine a
security header should be added to the outgoing SOAP message.</p><p>&lt;wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&gt;<br></br> &lt;wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;<br></br> &lt;wsse:Username&gt;Gajaba&lt;/wsse:Username&gt;<br></br> &lt;wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"&gt;WNPznBN3PeLypKYXlwV7w9zJZ9o=&lt;/wsse:Password&gt;<br></br> &lt;wsse:Nonce&gt;ICAgICAgIDEwNDY0NDk1Mg==&lt;/wsse:Nonce&gt;<br></br> &lt;wsu:Created&gt;2006-08-28T11:52:27Z&lt;/wsu:Created&gt;<br></br> &lt;/wsse:UsernameToken&gt;<br></br> &lt;wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;<br></br> &lt;wsu:Created&gt;2006-08-28T11:52:27Z&lt;/wsu:Created&gt;<br></br> &lt;wsu:Expires&gt;2006-08-28T11:58:27Z&lt;/wsu:Expires&gt;<br></br> &lt;/wsu:Timestamp&gt;<br></br>&lt;/wsse:Security&gt;<br></br></p><p><strong>Note: </strong>For the above sample we have used the same axis2.xml file for
both server and the client. But in the real world this is not possible. In
such a situation you can specify a client home as an argument.</p>
<div class="source"><pre>./echo [endpoint_url] [path to your client_home]
</pre></div>
</div><div class="subsection"><a name="Semantics_of_Parameters_Specified_in_axis2_xml"></a><h3>Semantics of Parameters Specified in axis2.xml</h3><table class="bodyTable"><tbody>
<tr class="b"><td><strong>Parameter</strong></td><td><strong>Semantic</strong></td></tr>
<tr class="a"><td>items</td><td>Specify the tokens to be used for the credential exchange. In the
above example we used both UsernameTokens and Timestamps</td></tr>
<tr class="b"><td>user</td><td>The username of the UsernameToken</td></tr>
<tr class="a"><td>passwordType</td><td>The way password is delivered. This can be either passwordText or
the passwordDigest. The former delivers password in plainText whilst
the latter delivers the hashed value of the password. Default is
passwordText</td></tr>
<tr class="b"><td>passwordCallbackClass</td><td>The module that provides the password for a particular user</td></tr>
<tr class="a"><td>timeToLive</td><td>The validity period of the TimestampToken after issuing. The time
is in seconds. In the above example, it's 6 minutes. If not
specified, the default is 5 minutes</td></tr>
</tbody></table><p><a id="Writing_own_password_callback_module"></a></p></div><div class="subsection"><a name="Writing_Your_Own_Password_Callback_Module"></a><h3>Writing Your Own Password Callback Module</h3><p>The Rampart module is not dependent on the way that passwords are stored.
For example, you may have passwords in a flat file or in a secured database.
What ever the way, Rampart expects a password callback module to retrieve
passwords for a given username. The sample coming under
"&lt;axis2c_home&gt;rampart/samples/callback" is a simple one containing a
few hard-coded passwords. It assigns a function to the function pointer.</p>
<div class="source"><pre>rcb-&gt;ops-&gt;callback_password = get_sample_password;
</pre></div>
<p><code>callback_password</code> is a function pointer to any function which
has the following signature.</p>
<div class="source"><pre>*
your_function(rampart_callback_t *rcb,
const axis2_env_t *env, const axis2_char_t *username)
</pre></div>
<p><code>your_function</code> should return the password as
<code>axis2_char_t</code>* per the username specified, if any. Inside your
function, you may write your code to supply stored passwords.</p><p>Then the path to the callback module needs to be specified in axis2.xml
under passwordCallbackClass. [The word Class, instead of Module is only for
compatibility with java implementation]</p><p><a id="Adding_security_parameters_dynamically"></a></p></div><div class="subsection"><a name="Adding_Security_Parameters_Dynamically"></a><h3>Adding Security Parameters Dynamically</h3><p>Outflow parameters specified in the axis2.xml can be added dynamically in
the client level. This can be done as shown in the following sample code.</p>
<div class="source"><pre> un_property = axis2_property_create(env);
AXIS2_PROPERTY_SET_VALUE(un_property, env, "Gajaba");
AXIS2_OPTIONS_SET_PROPERTY(options, env, RAMPART_ACTION_USER, un_property);
</pre></div>
<p>The above code will set the username parameter dynamically. All the values
specified in the axis2.xml will be overridden by the dynamic settings.</p></div><div class="subsection"><a name="References"></a><h3>References</h3><ul>
<li>Introducing Apache Axis2/C - <a href="http://www.wso2.net/articles/axis2/c/2006/09/04/introduction" class="externalLink" title="External Link">http://www.wso2.net/articles/axis2/c/2006/09/04/introduction</a></li>
<li>Introducing Rampart/C- <a href="http://www.wso2.net/articles/rampart/c/2006/09/19/introduction" class="externalLink" title="External Link">http://www.wso2.net/articles/rampart/c/2006/09/19/introduction</a></li>
</ul></div></div></div></div><div class="clear"><hr></hr></div><div id="footer"><div class="xright">© 2005-2006, Apache Software Foundation</div><div class="clear"><hr></hr></div></div></body></html>