Introduction
To communicate with the SoftRules® Service using TCP/IP an XML document or command has to be send to a specific TCP Port number at a specific IP address. This Port can be set using the Configuration Manager. This Port is coupled to a Configuration or the Configuration is specified in the request itself (TCP - DISPATCH Port).
The following functions are available using the server:
-
-
-
-
Process XML (XML In -> XML Out)
-
Process XML (XML In -> UI XML Out)
The descriptions of these functionalities are provided with programming examples in C#. Obviously the functionality SoftRules® is not limited to applications developed for the .Net framework.
Example
Here's an example in C# for sending an XML document to SoftRules® usin TCP/IP.
private string sendXml(string xml)
{
const int READBUFSIZE = 8196;
const int SENDBUFSIZE = 8196;
TcpClient m_Client = null;
Stopwatch m_TimeBetweenPackages = new Stopwatch();
string m_IP = '127.0.0.1';
string m_TCPPort = '56000';
string m_ResultString = "";
try
{
m_Client = new TcpClient(m_IP, m_TCPPort);
m_Client.ReceiveBufferSize = READBUFSIZE;
m_Client.SendBufferSize = SENDBUFSIZE;
if (m_Client.Connected)
{
//write
string signature = "SoftRules";
byte[] signatureBytes = Encoding.UTF8.GetBytes(signature);
byte[] requestBytes = Encoding.UTF8.GetBytes(xml);
byte[] LengthBytes = BitConverter.GetBytes(requestBytes.Length);
byte[] totalRequestBytes = new byte[signatureBytes.Length + LengthBytes.Length + requestBytes.Length];
System.Buffer.BlockCopy(signatureBytes, 0, totalRequestBytes, 0, signatureBytes.Length);
System.Buffer.BlockCopy(LengthBytes, 0, totalRequestBytes, signatureBytes.Length, LengthBytes.Length);
System.Buffer.BlockCopy(requestBytes, 0, totalRequestBytes, signatureBytes.Length + LengthBytes.Length, requestBytes.Length);
MemoryStream mStream = new MemoryStream(totalRequestBytes);
byte[] sendBuffer = new byte[SENDBUFSIZE];
int read = 0;
while ((read = mStream.Read(sendBuffer, 0, sendBuffer.Length)) > 0)
{
m_Client.GetStream().Write(sendBuffer, 0, read);
}
//read
byte[] rcvBuffer = new byte[READBUFSIZE];
byte[] totalBuffer = new byte[0];
int recvMsgSize = m_Client.GetStream().Read(rcvBuffer, 0, m_Client.ReceiveBufferSize);
byte[] lengthBytes = new Byte[4];
System.Buffer.BlockCopy(rcvBuffer, 0, signatureBytes, 0, 9);
System.Buffer.BlockCopy(rcvBuffer, 9, lengthBytes, 0, 4);
if (Encoding.UTF8.GetString(signatureBytes) == "SoftRules")
{
int lengthRequest = BitConverter.ToInt32(lengthBytes, 0);
totalBuffer = new Byte[lengthRequest];
int totalBytesReceived = recvMsgSize - 13;
System.Buffer.BlockCopy(rcvBuffer, 13, totalBuffer, 0, recvMsgSize - 13);
m_TimeBetweenPackages.Start(); //start stopwatch for max 5 sec.
bool bStopReceiving = false;
while ((totalBytesReceived < lengthRequest) && (!bStopReceiving))
{
if (m_Client.Available > 0)
{
recvMsgSize = m_Client.GetStream().Read(rcvBuffer, 0, m_Client.ReceiveBufferSize);
System.Buffer.BlockCopy(rcvBuffer, 0, totalBuffer, totalBytesReceived, recvMsgSize);
totalBytesReceived += recvMsgSize;
}
if (m_TimeBetweenPackages.ElapsedMilliseconds > 5000)
{
bStopReceiving = true;
}
}
m_ResultString = Encoding.UTF8.GetString(totalBuffer);
}
}
}
catch (SocketException se)
{
throw se;
}
catch (Exception e)
{
throw e;
}
finally
{
if (m_Client != null)
{
if (m_Client.Client != null)
{
m_Client.Client.Close();
}
m_Client.Close();
}
}
return m_ResultString;
}
Response
The server returns an XML document following this schema (XSD):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="softrulestcpframe">
<xs:complexType>
<xs:sequence>
<xs:element ref="softrules" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="softrules">
<xs:complexType>
<xs:sequence>
<xs:element ref="header" minOccurs="1" maxOccurs="1"/>
<xs:element ref="result" minOccurs="0" maxOccurs="1"/>
<xs:element ref="xmldocument" minOccurs="0" maxOccurs="1"/>
<xs:element ref="status" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="result">
<xs:complexType>
<xs:sequence>
<xs:element ref="errorcode"/>
<xs:element ref="errordescription"/>
<xs:element ref="errordetail"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="errorcode" type="xs:integer"/>
<xs:element name="errordescription">
<xs:complexType/>
</xs:element>
<xs:element name="errordetail">
<xs:complexType/>
</xs:element>
<xs:element name="header">
<xs:complexType>
<xs:sequence>
<xs:element ref="functionid" minOccurs="1" maxOccurs="1"/>
<xs:element ref="configid" minOccurs="0" maxOccurs="1"/>
<xs:element ref="inadapter" minOccurs="0" maxOccurs="1"/>
<xs:element ref="outadapter" minOccurs="0" maxOccurs="1"/>
<xs:element ref="parameters" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="functionid" type="xs:integer"/>
<xs:element name="configid" type="xs:integer"/> <!-- Vereist bij een TCP Dispatch poort -->
<xs:element name="inadapter" type="xs:string"/> <!-- Vereist bij een TCP Dispatch poort -->
<xs:element name="outadapter" type="xs:string"/> <!-- Vereist bij een TCP Dispatch poort -->
<xs:element name="parameters">
<xs:complexType>
<xs:sequence>
<xs:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="parameter">
<xs:complexType>
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="value"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="name" type="xs:string"/>
<xs:element name="value" type="xs:string"/>
<xs:element name="xmldocument" type="xs:string"/> <!-- Dit is een CDATA section -->
<xs:element name="status" type="xs:string"/>
</xs:schema>
Messages
Messages can be custom made and passed to the server (Raise Exception). The system will also generate its own messages, like validation messages. By default SoftRules® will use message code 1 if no messagecode is used.
Messagecode 2 is about validation messages on the Input XML.
Messagecode 3 is about validation message on the Output XML.
<softrulestcpframe>
<softrules>
<result>
<configuration>O109 - Compleet bij Elkaar Pakket - Berekenen (1000)</configuration>
<function>ProcessXml (14)</function>
<messages>
<message>
<messagecode>2</messagecode>
<messagedescription>(1,422) Het element PP_INGDAT is ongeldig. De waarde 23-09-2011 is ongeldig volgens het bijbehorende gegevenstype Decimal - De Pattern-beperking is mislukt.</messagedescription>
<Severity>Error</Severity>
</message>
<message>
<messagecode>2</messagecode>
<messagedescription>(1,216) Het element PK_INGDAT is ongeldig. De waarde 23-09-2011 is ongeldig volgens het bijbehorende gegevenstype Decimal - De Pattern-beperking is mislukt.</messagedescription>
<Severity>Error</Severity>
</message>
<message>
<messagecode>3</messagecode>
<messagedescription>(1,7782) Het element PP_TKRT is ongeldig. De waarde € 0,00 is ongeldig volgens het bijbehorende gegevenstype Decimal - De tekenreeks € 0,00 is geen geldige Decimal waarde.</messagedescription>
<Severity>Error</Severity>
</message>
</messages>
</result>
<xmldocument/>
</softrules>
</softrulestcpframe>