Next: 9. Authentication Up: Sympa Mailing Lists Management Software version Previous: 7. WWSympa, Sympa's web interface Contents Index
Subsections

- 8.1 Introduction
- 8.2 Web server setup
- 8.3 Sympa setup
- 8.4 The WSDL service description
- 8.5 Client-side programming
  - 8.5.1 Writting a Java client with Axis

#
8. Sympa SOAP server

# 8.1 Introduction

SOAP is one protocol (generally over HTTP) that can be used to provide web services. Sympa SOAP server allows to access a Sympa service from within another program, written in any programming language and on any computer. SOAP encapsulates procedure calls, input parameters and resulting data in an XML data structure. The Sympa SOAP server's API is published in a WSDL document, retreived via Sympa's web interface.

The SOAP server provides a limited set of high level functions including `login`, `which`, `lists`,`subscribe`,`signoff`. Other functions might be implemented in the future.

The SOAP server uses SOAP::Lite Perl library. The server is running as a daemon (thanks to FastCGI), receiving the client SOAP requests via a web server (Apache for example).

# 8.2 Web server setup

You NEED TO install FastCGI for the SOAP server to work properly because it will run as a daemon.

Here is a sample piece of your Apache `httpd.conf` with a SOAP server configured :

    	FastCgiServer /sympa_soap_server.pl -processes 1
    	ScriptAlias /sympasoap /sympa_soap_server.pl

    	<Location /sympasoap>
       	  SetHandler fastcgi-script
    	</Location>

# 8.3 Sympa setup

The only parameters that you need to set in `sympa.conf`/`robot.conf` files is the `soap_url` parameter that defines the URL of the SOAP service corresponding to the ScriptAlias you've previously setup in Apache config.

This parameter is used to publish the SOAP service URL in the WSDL file (defining the API) but also for the SOAP server to deduce what Virtual Robot is concerned by the current SOAP request (a single SOAP server will serve all Sympa Virtual robots).

# 8.4 The WSDL service description

Here is what the WSDL file looks like before it is parsed by WWSympa :

    <?xml version="1.0"?>
    <definitions name="Sympa"
    	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    	targetNamespace="[conf->wwsympa_url]/wsdl"
    	xmlns:tns="[conf->wwsympa_url]/wsdl"
    	xmlns="http://schemas.xmlsoap.org/wsdl/"
    	xmlns:xsdl="[conf->soap_url]/wsdl">

    <!-- types part -->

    <types>
    <schema targetNamespace="[conf->wwsympa_url]/wsdl"
    	xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
    	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    	xmlns="http://www.w3.org/2001/XMLSchema">

    	<complexType name="ArrayOfLists">
    		<complexContent>
    			<restriction base="SOAP-ENC:Array">
    				<attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:listType[]"/>
    			</restriction>
    		</complexContent>
    	</complexType>

    	<complexType name="ArrayOfString">
    		<complexContent>
    			<restriction base="SOAP-ENC:Array">
    				<attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="string[]"/>
    			</restriction>
    		</complexContent>
    	</complexType>

    	<complexType name="listType">
               <all>
    		<element name="listAddress" minOccurs="1" type="string"/>
    		<element name="homepage" minOccurs="0" type="string"/>
    		<element name="isSubscriber" minOccurs="0" type="boolean"/>
    		<element name="isOwner" minOccurs="0" type="boolean"/>
    		<element name="isEditor" minOccurs="0" type="boolean"/>
    		<element name="subject" minOccurs="0" type="string"/>
               </all>
    	</complexType>
    </schema>
    </types>

    <!-- message part -->

    <message name="infoRequest">
            <part name="listName" type="xsd:string"/>
    </message>

    <message name="infoResponse">
    	<part name="return" type="tns:listType"/>
    </message>

    <message name="complexWhichRequest">
    </message>

    <message name="complexWhichResponse">
    	<part name="return" type="tns:ArrayOfLists"/>
    </message>

    <message name="whichRequest">
    </message>

    <message name="whichResponse">
    	<part name="return" type="tns:ArrayOfString"/>
    </message>

    <message name="amIRequest">
    	<part name="list" type="xsd:string"/>
    	<part name="function" type="xsd:string"/>
    	<part name="user" type="xsd:string"/>
    </message>

    <message name="amIResponse">
    	<part name="return" type="xsd:boolean"/>
    </message>

    <message name="reviewRequest">
    	<part name="list" type="xsd:string"/>
    </message>

    <message name="reviewResponse">
    	<part name="return" type="tns:ArrayOfString"/>
    </message>

    <message name="signoffRequest">
    	<part name="list" type="xsd:string"/>
    	<part name="email" type="xsd:string" xsd:minOccurs="0"/>
    </message>

    <message name="signoffResponse">
    	<part name="return" type="xsd:boolean"/>
    </message>

    <message name="subscribeRequest">
    	<part name="list" type="xsd:string"/>
    	<part name="gecos" type="xsd:string" xsd:minOccurs="0"/>
    </message>

    <message name="subscribeResponse">
    	<part name="return" type="xsd:boolean"/>
    </message>

    <message name="loginRequest">
    	<part name="email" type="xsd:string"/>
    	<part name="password" type="xsd:string"/>
    </message>

    <message name="loginResponse">
    	<part name="return" type="xsd:string"/>
    </message>

    <message name="authenticateAndRunRequest">
    	<part name="email" type="xsd:string"/>
    	<part name="cookie" type="xsd:string"/>
    	<part name="service" type="xsd:string"/>
    	<part name="parameters" type="tns:ArrayOfString" xsd:minOccurs="0"/>
    </message>

    <message name="authenticateAndRunResponse">
    	<part name="return" type="tns:ArrayOfString" xsd:minOccurs="0"/>
    </message>

    <message name="casLoginRequest">
    	<part name="proxyTicket" type="xsd:string"/>
    </message>

    <message name="casLoginResponse">
    	<part name="return" type="xsd:string"/>
    </message>

    <message name="listsRequest">
    	<part name="topic" type="xsd:string" xsd:minOccurs="0"/>
    	<part name="subtopic" type="xsd:string" xsd:minOccurs="0"/>
    </message>

    <message name="listsResponse">
    	<part name="listInfo" type="xsd:string"/>
    </message>

    <message name="complexListsRequest">
    </message>

    <message name="complexListsResponse">
    	<part name="return" type="tns:ArrayOfLists"/>
    </message>

    <message name="checkCookieRequest">
    </message>

    <message name="checkCookieResponse">
    	<part name="email" type="xsd:string"/>
    </message>

    <!-- portType part -->

    <portType name="SympaPort">
    	<operation name="info">
    		<input message="tns:infoRequest" />
    		<output message="tns:infoResponse" />
    	</operation>
    	<operation name="complexWhich">
    		<input message="tns:complexWhichRequest" />
    		<output message="tns:complexWhichResponse" />
    	</operation>
    	<operation name="which">
    		<input message="tns:whichRequest" />
    		<output message="tns:whichResponse" />
    	</operation>
    	<operation name="amI">
    		<input message="tns:amIRequest" />
    		<output message="tns:amIResponse" />
    	</operation>
    	<operation name="review">
    		<input message="tns:reviewRequest" />
    		<output message="tns:reviewResponse" />
    	</operation>
    	<operation name="subscribe">
    		<input message="tns:subscribeRequest" />
    		<output message="tns:subscribeResponse" />
    	</operation>
    	<operation name="signoff">
    		<input message="tns:signoffRequest" />
    		<output message="tns:signoffResponse" />
    	</operation>
    	<operation name="login">
    		<input message="tns:loginRequest" />
    		<output message="tns:loginResponse" />
    	</operation>
    	<operation name="casLogin">
    		<input message="tns:casLoginRequest" />
    		<output message="tns:casLoginResponse" />
    	</operation>
    	<operation name="authenticateAndRun">
    		<input message="tns:authenticateAndRunRequest" />
    		<output message="tns:authenticateAndRunResponse" />
    	</operation>
    	<operation name="lists">
    		<input message="tns:listsRequest" />
    		<output message="tns:listsResponse" />
    	</operation>
    	<operation name="complexLists">
    		<input message="tns:complexListsRequest" />
    		<output message="tns:complexListsResponse" />
    	</operation>
    	<operation name="checkCookie">
    		<input message="tns:checkCookieRequest" />
    		<output message="tns:checkCookieResponse" />
    	</operation>
    </portType>

    <!-- Binding part -->

    <binding name="SOAP" type="tns:SympaPort">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    	<operation name="info">
    		<soap:operation soapAction="urn:sympasoap#info"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="complexWhich">
    		<soap:operation soapAction="urn:sympasoap#complexWhich"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="which">
    		<soap:operation soapAction="urn:sympasoap#which"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="amI">
    		<soap:operation soapAction="urn:sympasoap#amI"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="review">
    		<soap:operation soapAction="urn:sympasoap#review"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="subscribe">
    		<soap:operation soapAction="urn:sympasoap#subscribe"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="signoff">
    		<soap:operation soapAction="urn:sympasoap#signoff"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="login">
    		<soap:operation soapAction="urn:sympasoap#login"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="casLogin">
    		<soap:operation soapAction="urn:sympasoap#casLogin"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="authenticateAndRun">
    		<soap:operation soapAction="urn:sympasoap#authenticateAndRun"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="lists">
    		<soap:operation soapAction="urn:sympasoap#lists"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="complexLists">
    		<soap:operation soapAction="urn:sympasoap#complexLists"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    	<operation name="checkCookie">
    		<soap:operation soapAction="urn:sympasoap#checkCookie"/>
    			<input>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			<output>
    				<soap:body use="encoded"
    					namespace="urn:sympasoap"
    					encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</output>
    	</operation>
    </binding>

    <!-- service part -->

    <service name="SympaSOAP">
    	<port name="SympaPort" binding="tns:SOAP">
    		<soap:address location="[conf->soap_url]"/>
    	</port>
    </service>

    </definitions>

# 8.5 Client-side programming

Sympa is distributed with 2 sample clients written in Perl and in PHP. Sympa SOAP server has also been successfully tested with a UPortal Chanel as a Java client (using Axis). The sample PHP SOAP client has been installed on our demo server : http://demo.sympa.org/sampleClient.php.

Depending on your programming language and the SOAP library you're using, you will either directly contact the SOAP service (as with Perl SOAP::Lite library) or first load the WSDL description of the service (as with PHP nusoap or Java Axis). Axis is able to create a stub from the WSDL document.

The WSDL document describing the service should be fetch through WWSympa's dedicated URL : http://your.server/wws/wsdl.

Note : the login() function maintains a login session using HTTP cookies. If you are not able to maintain this session by analysing and sending appropriate cookies under SOAP, then you should use the authenticateAndRun() function that does not require cookies to authenticate.

## 8.5.1 Writting a Java client with Axis

First, download jakarta-axis (http://ws.apache.org/axis/)

You must add the libraries provided with jakarta axis (v >1.1) to you CLASSPATH. These libraries are :

- axis.jar
- saaj.jar
- commons-discovery.jar
- commons-logging.jar
- xercesImpl.jar
- jaxrpc.jar
- xml-apis.jar
- jaas.jar
- wsdl4j.jar
- soap.jar

Next, you have to generate client java classes files from the sympa WSDL url. Use the following command :

java org.apache.axis.wsdl.WSDL2Java -av WSDL_URL

For example :

    java org.apache.axis.wsdl.WSDL2Java -av  http://demo.sympa.org/wws/wsdl

Exemple of screen output during generation of java files :

    Parsing XML file:  http://demo.sympa.org/wws/wsdl
    Generating org/sympa/demo/wws/msdl/ListType.java
    Generating org/sympa/demo/wws/msdl/SympaPort.java
    Generating org/sympa/demo/wws/msdl/SOAPStub.java
    Generating org/sympa/demo/wws/msdl/SympaSOAP.java
    Generating org/sympa/demo/wws/msdl/SympaSOAPLocator.java

If you need more information or more generated classes (to have the server-side classes or junit testcase classes for example), you can get a list of switches :

    java org.apache.axis.wsdl.WSDL2Java -h

The reference page is :
http://ws.apache.org/axis/java/reference.html

Take care of Test classes generated by axis, there are not useable as is. You have to stay connected between each test. To use junit testcases, before each soap operation tested, you must call the authenticated connexion to sympa instance.

Here is a simple Java code that invokes the generated stub to perform a casLogin() and a which() on the remote Sympa SOAP server :

    SympaSOAP loc = new SympaSOAPLocator();
    ((SympaSOAPLocator)loc).setMaintainSession(true);
    SympaPort tmp = loc.getSympaPort();
    String _value = tmp.casLogin(_ticket);
    String _cookie = tmp.checkCookie();
    String[] _abonnements = tmp.which();

Next: 9. Authentication Up: Sympa Mailing Lists Management Software version Previous: 7. WWSympa, Sympa's web interface Contents Index