SCA

SOAP Example

worldclock.c
Example service implementation code and XML artifacts demonstrate how to provide the worldclock service as a SOAP service, and show how to use WSDL and the SDO API to enable XML Schema-typed, input-validated access to request and response data
worldclock.wsdl
WSDL file
worldclock.composite
Composite file

worldclock.c

#include <stdio.h>

#include "SDO.h"
#include "SCA.h"

static int utc_timezone_offset(char *city);
static int calculate_time_diff(int hour, char *city, char *otherCity);

/*
 * Implementation of worldclock service. 
 */
DATAOBJECT getLocalTimeForCity(DATAOBJECT request) {
		
	SDOFACTORY df = getDataFactory();

	SDOTYPE requestType = getType(request);
	if (requestType == 0) {
		requestType = findType(df,
			"http://www.example.com/worldclock.xsd",
			"worldclockRequest");
	}
	
	SDOPROPERTY requestTimeProp = getTypePropertyByName(requestType, "local-time");
	DATAOBJECT requestTimeObj = getDataObject(request, requestTimeProp);
	SDOPROPERTY cityProp = getTypePropertyByName(getPropertyType(requestTimeProp), "city");
	char* requestCity = getCString(requestTimeObj, cityProp);
	SDOPROPERTY hourProp = getTypePropertyByName(getPropertyType(requestTimeProp), "hour");
	int requestTime = getInt(requestTimeObj, hourProp);

	SDOPROPERTY otherCityProp = getTypePropertyByName(requestType, "city-to-request-time-for");
	char *requestOtherCity = getCString(request, otherCityProp);

	int time_diff = calculate_time_diff(requestTime, requestCity, requestOtherCity);

	// error handling: create a SOAP fault
	if (time_diff < -24 || time_diff > 24) {
		int compcode, reason;
		DATAOBJECT faultResponse = doAlloc(df,
			"http://www.w3.org/2001/XMLSchema",
			"anyType");
		setCStringByName(faultResponse,
			"faultstring",
			"unrecognized city name");
		SCASetFaultMessage("worldclock",
			"getLocalTimeForCity",
			"worldclock-fault",
			0,
			faultResponse,
			&compcode,
			&reason);
		return 0;
	}

	SDOTYPE responseType = findType(df,
		/* "http://www.example.com/worldclock.xsd", */
		getURI(requestType),
		"worldclockResponse");

	SDOTYPE timeType = findType(df,
		/* "http://www.example.com/worldclock.xsd", */
		getURI(requestType),
		"time");

	DATAOBJECT response = doAllocByType(getDataFactory(), responseType);
	DATAOBJECT responseTime = doAllocByType(getDataFactory(), timeType);

	setCStringByName(responseTime, "city", requestOtherCity);
	setIntByName(responseTime, "hour", time_diff);

	SDOPROPERTY responseTimeProp = getTypePropertyByName(responseType, "remote-time");
	setDataObject(response, responseTimeProp, responseTime);

	return response;
}

static int calculate_time_diff(int hour, char *city, char *otherCity) {
	return hour + utc_timezone_offset(city) - utc_timezone_offset(otherCity); 
}

static int utc_timezone_offset(char *city) {
	if (!strcmp("Bangalore", city)) return +5;
	if (!strcmp("Berlin", city)) return +1;
	if (!strcmp("San Francisco", city)) return -8;

	// ...

	// return 100 to indicate unknown argument city
	return 100;
}

worldclock.wsdl

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
  targetNamespace="http://www.example.com/worldclock.wsdl"
  xmlns="http://www.example.com/worldclock.wsdl"
  xmlns:t="http://www.example.com/worldclock.xsd"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
  xsi:schemaLocation="http://www.w3.org/ns/wsdl http://www.w3.org/2007/06/wsdl/wsdl20.xsd">

	<wsdl:types>

		<xs:schema targetNamespace="http://www.example.com/worldclock.xsd"
			          elementFormDefault="qualified">

			<xs:complexType name="time">
				<xs:sequence>
					<xs:element name="city" type="xs:string"/>
					<xs:element name="hour" type="xs:int"/>
				</xs:sequence>
			</xs:complexType>

			<xs:complexType name="worldclockRequest">
				<xs:sequence>
					<xs:element name="local-time" type="t:time"/>
					<xs:element name="city-to-request-time-for" type="xs:string"/>
				</xs:sequence>
			</xs:complexType>

			<xs:complexType name="worldclockResponse">
				<xs:sequence>
					<xs:element name="remote-time" type="t:time"/>
				</xs:sequence>
			</xs:complexType>

			<xs:element name="worldclockRequest" type="t:worldclockRequest"/>
			<xs:element name="worldclockResponse" type="t:worldclockResponse"/>
		</xs:schema>

	</wsdl:types>

	<wsdl:message name="worldclockRequest">
  		<wsdl:part name="request" element="t:worldclockRequest"/>
	</wsdl:message>

	<wsdl:message name="worldclockResponse">
  		<wsdl:part name="response" element="t:worldclockResponse"/>
	</wsdl:message>

	<wsdl:message name="worldclockFaultResponse">
  		<wsdl:part name="message" element="xs:string"/>
</wsdl:message>

<wsdl:portType name="worldclock-ops">
	<wsdl:operation name="getLocalTimeForCity">
		<wsdl:input message="worldclock-request"
		            wsaw:Action="http://www.example.com/worldclock/getLocalTimeForCity"/>
		<wsdl:output message="worldclock-response"/>
		<wsdl:fault name="worldclock-fault" message="worldclock-fault-response"/>
	</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="soap-binding" type="worldclock-ops">

  	<soap:binding style="document"
		              transport="http://schemas.xmlsoap.org/soap/http"/>

		<wsdl:operation name="getLocalTimeForCity">
    			<soap:operation soapAction="http://www.example.com/worldclock.wsdl/getLocalTimeForCity"/>
			<wsdl:input>
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
    			</wsdl:output>
			<wsdl:fault name="worldclock-fault">
				<soap:fault name="worldclock-fault" use="literal"/>
			</wsdl:fault>
		</wsdl:operation>
</wsdl:binding>

<wsdl:service name="worldclock-service">
	<wsdl:port name="workdclock-ops" binding="soap-binding">
		<soap:address location="http://localhost:9090/services/worldclock"/>
	</wsdl:port>
</wsdl:service>

</wsdl:definitions>

worldclock.composite

<?xml version="1.0" encoding="ASCII"?>
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
           targetNamespace="http://www.pmsca.com"
           name="WorldclockComposite">

	<!-- expose worldclock via wsdl/SOAP -->
	<service name="worldclock" promote="worldclock-impl">
		<interface.wsdl interface="http://www.pmsca.com/worldclock.wsdl#wsdl.interface(worldclock-ops)"/>
		<binding.ws wsdlElement="http://www.pmsca.com/worldclock.wsdl1#wsdl.port(worldclock-ops)"/>
	</service>

	<!-- worldclock implementation -->
	<component name="worldclock-impl">
		<service name="worldclock"/>
		<implementation.c module="worldclock" library="true" componentType=""/>
	</component>
</composite>