Asynchronous Web Services

From Agility
Revision as of 12:18, 21 June 2016 by Sychu (Talk | contribs)

Jump to: navigation, search

Introduction

Base principal of asynchronous processing is to store request data (from web service client) in queue and immediately respond with simple acknowledgement. From client point of view acknowledge means that his message is delivered and pending processing. Web service host process (import) received data in separate thread. Advantage of asynchronous processing is that client do not have to wait for time consuming processing (big data volume). Network connection can be easily broken and it is important to keep it as short as possible. Action after processing of message depend on agreement. Possible scenarios:

  1. Client don’t expect processing results (send ad forget)
  2. Client will periodically call sever and asks for results (until processed)
  3. Client expects that server will always send back result.
  4. Client expects that server will send back result only when processing fail.

Currently supported are only first two patterns. To support scenario 3 & 4 import result should be pushed to export queue with appropriate endpoint setup (standard, error).

Async process.png

  • Note that block "Crete Request With Result" is not implemented.

Asynchronous Web Service Definition

To enable Asynchronous Import setup Storage Type as "AsyncWebService".

Import def form.png


Asynchronous import definition consists of regular import and additional section <ack>…<ack>. Inside ack element defined is additional separate import definition (full featured) which is responsible for generating acknowledgement. Import form ack section is processed first and import result is responded to client immediately. After respond main import is processed asynchronously (in separate thread). Result is stored in syImpExpQueue.AsyncResult.

Queue det formAsync result.png

<?xml version="1.0" encoding="utf-8"?>
<import>
	<!-- =======================================================
	ACKnowledgement hander 
	============================================================ -->
	<ack>
		<resultexport>
			<contents>
				<data type="template-xml">
					<ack>OK</ack>
				</data>
			</contents> 
		</resultexport>	
	</ack>

	<!-- =======================================================
	Standard import processed asynchronously in separate thread 
	============================================================ -->
	<namespaces>
		<namespace name="wo" uri="http://www.fastnetasp.com/GeneralImport/WO"/>
		<namespace name="soap" uri="http://www.w3.org/2003/05/soap-envelope"/>
	</namespaces>
	<mappings classname="Control.GeneralInterface.XMLFileImport">	
		<table name="JobList" xpath="soap:Envelope/soap:Body/wo:UpdateJob/wo:JobList/wo:woJob">
			<field name="JobCode" xpath="wo:JobCode"/>
			<field name="Description" xpath="wo:Description"/>
			<field name="JobStatus" xpath="wo:JobStatus"/>
			<field name="JobType" xpath="wo:JobType"/>			
			<table name="JobTask" xpath="wo:woJobTask">
				<field name="TaskCode" xpath="wo:TaskCode"/>
				<field name="TaskDescription" xpath="wo:Description"/>
				<field name="TaskType" xpath="wo:TaskType"/>
				<field name="TaskStatus" xpath="wo:TaskStatus"/>
			</table>
		</table>
	</mappings>



	<assign classname="Control.GeneralInterface.StandardImportProcessor">
		<businessobject classname="DataBO.ProcessMngt.JobBO">
			<table name="woJob" sourceTable="JobList">
				<identification>
					woJob.JobCode = #Import.JobCode
				</identification>
				<mode>
					<update/>
				</mode>			
				<set>
					<field name="JobStatusID">Lookup("DataBO.SystemData.JobStatusBO","syJobStatus","Code",#Import.JobStatus,"JobStatusID")</field>
					<field name="FullDescription">#Import.Description</field>
				</set>
			</table>
		</businessobject>
	</assign>

	<resultexport>
		<contents defaulttype="template-xml">
			<data>
				<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
					<soap:Body>
						<UpdateJobResponse xmlns="http://www.fastnetasp.com/GeneralImport/WO">
							<UpdateJobResult>
							{:include "jobresults"}
							</UpdateJobResult>
						</UpdateJobResponse>
					</soap:Body>
				</soap:Envelope>
			</data>

			<partial name="jobresults">
				<foreach table="JobList" datacontext="mappings" classname="DataBO.ProcessMngt.JobBO">	
					<data>	
						<woJobResult>
							<JobCode>{woJob.JobCode}</JobCode>
							<StatusCode>
								{:if #Result.IsImported}OK{:else}ERROR{:endif}
							</StatusCode>
							<StatusDescription>{#Result.Message}</StatusDescription>
						</woJobResult>
					</data>
				</foreach>
			</partial>		
		</contents>
	</resultexport>
</import>