How to Use TCP Transport¶
Sending multiple messages via the same TCP channel
Generally, you can send only one message via one generic TCP channel. Nevertheless, the Micro Integrator also supports sending multiple messages via the same TCP channel by splitting them in different ways. Hence, the TCP transport needs to determine the end of the message that is mediated through the Micro Integrator to split it by a character, a sequence of characters, message length, or special characters in hex form. The client can select which input type to use to send the request to the TCP proxy out of the available options (i.e., binary and String). Splitting the message by a single character is the most efficient method.
You can split the following sample request input message in different ways as explained below.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>
The following are the properties that are specific to sending multiple messages via the same TCP channel.
Property | Description | Required | Possible Values | Default Value |
---|---|---|---|---|
recordDelimiterType | Type of the record delimiter you use to split the message | No | Character, byte or String | String |
recordDelimiter | The delimiter of the record you use to split the message | No | A valid value that matches the specified delimiter type | N/A |
recordLength | Length of the message to be split. If you set this, then the delimiter properties are omitted. | No | A valid integer value. This will be identified in bytes. | N/A |
inputType | Input type of the message | No | String or binary | String |
The following are the transport receiver properties.
Property | Description | Required | Possible Values | Default Value |
---|---|---|---|---|
port | The port on which the TCP server should listen for incoming messages | No | A positive integer less than 65535 | 8000 |
hostname | The host name of the server to be displayed in WSDLs, etc. | No | A valid host name or an IP address | N/A |
contentType | The content type of the input message | No | A valid content type (e.g., application/xml, application/json, text/html etc.) | N/A |
responseClient | Whether the client needs to get the response or not | No | True or false | true |
Prerequisites¶
Example 1: Splitting by a character¶
Synapse configurations¶
The following proxy service splits the message by a character. It receives a message with an empty body, which it will forward to the HTTP endpoint after enriching the body with the symbolic value "IBM
".
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="TCPProxy" startOnLoad="true" transports="tcp" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<property name="symbol" scope="default" type="STRING" value="IBM"/>
<enrich description="Replace the body content.">
<source clone="true" type="inline">
<m:getQuote xmlns:m="http://services.samples">
<m:request>
<m:symbol>?</m:symbol>
</m:request>
</m:getQuote>
</source>
<target action="replace" type="body"/>
</enrich>
<enrich description="Replace the symbol value with the value from the 'symbol' property.">
<source clone="true" property="symbol" type="property"/>
<target action="replace" xpath="//m:getQuote/m:request/m:symbol" xmlns:m="http://services.samples"/>
</enrich>
<log category="INFO" level="full" separator=","/>
<header name="Action" action="set" scope="default" value="urn:getQuote"/>
<call>
<endpoint key="SimpleStockQuoteServiceEp"/>
</call>
<log category="INFO" level="full"/>
<respond/>
</inSequence>
<faultSequence/>
</target>
<parameter name="transport.tcp.responseClient">true</parameter>
<parameter name="transport.tcp.recordDelimiter">|</parameter>
<parameter name="transport.tcp.inputType">string</parameter>
<parameter name="transport.tcp.port">6061</parameter>
<parameter name="transport.tcp.recordDelimiterType">character</parameter>
<parameter name="transport.tcp.contentType">text/xml</parameter>
</proxy>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="SimpleStockQuoteServiceEp" xmlns="http://ws.apache.org/ns/synapse">
<address uri="http://localhost:9000/services/SimpleStockQuoteService">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
Build and run (example 1)¶
Create the artifacts:
-
Launch Visual Studio Code with the Micro Integrator for VS Code extension (MI for VS Code) installed.
Info
Follow the Install Micro Integrator for VS Code documentation for a complete installation guide.
-
Create an integration project.
- Create the proxy service with the configurations given above.
- Deploy the artifacts in your Micro Integrator.
Set up the back-end service.
- Download the back-end service.
- Extract the downloaded zip file.
- Open a terminal, navigate to the
axis2Server/bin/
directory inside the extracted folder. -
Execute the following command to start the axis2server with the SimpleStockQuote back-end service:
sh axis2server.sh
axis2server.bat
Send the following message via TCP to the TCP listener port.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>|<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>
netcat localhost 6061 < request.xml
Example 2: Splitting by a special character¶
Synapse configuration¶
The sample proxy below splits the input message by appending a special character to the end of the message.
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="TCPProxy" startOnLoad="true" transports="tcp" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<property name="symbol" scope="default" type="STRING" value="IBM"/>
<enrich description="Replace the body content.">
<source clone="true" type="inline">
<m:getQuote xmlns:m="http://services.samples">
<m:request>
<m:symbol>?</m:symbol>
</m:request>
</m:getQuote>
</source>
<target action="replace" type="body"/>
</enrich>
<enrich description="Replace the symbol value with the value from the 'symbol' property.">
<source clone="true" property="symbol" type="property"/>
<target action="replace" xpath="//m:getQuote/m:request/m:symbol" xmlns:m="http://services.samples"/>
</enrich>
<log category="INFO" level="full" separator=","/>
<header name="Action" action="set" scope="default" value="urn:getQuote"/>
<call>
<endpoint key="SimpleStockQuoteServiceEp"/>
</call>
<log category="INFO" level="full"/>
<respond/>
</inSequence>
<faultSequence/>
</target>
<parameter name="transport.tcp.recordDelimiter">0x03</parameter>
<parameter name="transport.tcp.responseClient">true</parameter>
<parameter name="transport.tcp.inputType">binary</parameter>
<parameter name="transport.tcp.port">6061</parameter>
<parameter name="transport.tcp.recordDelimiterType">byte</parameter>
<parameter name="transport.tcp.contentType">text/xml</parameter>
</proxy>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="SimpleStockQuoteServiceEp" xmlns="http://ws.apache.org/ns/synapse">
<address uri="http://localhost:9000/services/SimpleStockQuoteService">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
Build and run (example 2)¶
Create the artifacts:
-
Launch Visual Studio Code with the Micro Integrator for VS Code extension (MI for VS Code) installed.
Info
Follow the Install Micro Integrator for VS Code documentation for a complete installation guide.
-
Create an integration project.
- Create the proxy service with the configurations given above.
- Deploy the artifacts in your Micro Integrator.
Set up the back-end service.
- Download the back-end service.
- Extract the downloaded zip file.
- Open a terminal, navigate to the
axis2Server/bin/
directory inside the extracted folder. -
Execute the following command to start the axis2server with the SimpleStockQuote back-end service:
sh axis2server.sh
axis2server.bat
Send the following message via TCP to the TCP listener port.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>
request.xml
file and use Netcat to send the TCP request.
netcat localhost 6061 < request.xml
Example 3: Splitting by a character sequence¶
Synapse configuration¶
The sample proxy below splits the input message by a sequence of characters.
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="TCPProxy" startOnLoad="true" transports="tcp" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<property name="symbol" scope="default" type="STRING" value="IBM"/>
<enrich description="Replace the body content.">
<source clone="true" type="inline">
<m:getQuote xmlns:m="http://services.samples">
<m:request>
<m:symbol>?</m:symbol>
</m:request>
</m:getQuote>
</source>
<target action="replace" type="body"/>
</enrich>
<enrich description="Replace the symbol value with the value from the 'symbol' property.">
<source clone="true" property="symbol" type="property"/>
<target action="replace" xpath="//m:getQuote/m:request/m:symbol" xmlns:m="http://services.samples"/>
</enrich>
<log category="INFO" level="full" separator=","/>
<header name="Action" action="set" scope="default" value="urn:getQuote"/>
<call>
<endpoint key="SimpleStockQuoteServiceEp"/>
</call>
<log category="INFO" level="full"/>
<respond/>
</inSequence>
<faultSequence/>
</target>
<parameter name="transport.tcp.responseClient">true</parameter>
<parameter name="transport.tcp.recordDelimiter">split</parameter>
<parameter name="transport.tcp.inputType">string</parameter>
<parameter name="transport.tcp.port">6061</parameter>
<parameter name="transport.tcp.recordDelimiterType">string</parameter>
<parameter name="transport.tcp.contentType">text/xml</parameter>
</proxy>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="SimpleStockQuoteServiceEp" xmlns="http://ws.apache.org/ns/synapse">
<address uri="http://localhost:9000/services/SimpleStockQuoteService">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
Build and run (example 3)¶
Create the artifacts:
-
Launch Visual Studio Code with the Micro Integrator for VS Code extension (MI for VS Code) installed.
Info
Follow the Install Micro Integrator for VS Code documentation for a complete installation guide.
-
Create an integration project.
- Create the proxy service with the configurations given above.
- Deploy the artifacts in your Micro Integrator.
Set up the back-end service.
- Download the back-end service.
- Extract the downloaded zip file.
- Open a terminal, navigate to the
axis2Server/bin/
directory inside the extracted folder. -
Execute the following command to start the axis2server with the SimpleStockQuote back-end service:
sh axis2server.sh
axis2server.bat
Send the following message via TCP to the TCP listener port.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>split<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body/></soapenv:Envelope>
On macOS, you can save the request in a request.xml
file and use Netcat to send the TCP request.
nc localhost 6061 < request.xml
Developing the Java client for the transport¶
The sample Java Client below splits the input message by a special character. Also, you can develop a character delimiter client by changing the below client accordingly.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class TCPClient {
String host = "localhost";
int port = 6061;
Socket socket = null;
int count = 0;
public static void main(String args[]) throws Exception {
Character aByte = 0x10;
TCPClient client = new TCPClient();
String message = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<soapenv:Header/><soapenv:Body/></soapenv:Envelope>" + aByte;
client.sendToServer(message);
client.recieveFromServer();
client.sendToServer(message);
client.recieveFromServer();
client.close();
}
TCPClient() throws Exception {
socket = new Socket(host, port);
}
void sendToServer(String msg) throws Exception {
//create output stream attached to socket
PrintWriter outToServer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//send msg to server
outToServer.print(msg);
outToServer.flush();
}
void recieveFromServer() throws Exception {
char delimiter = 0x10;
InputStream inFromServer = socket.getInputStream();
//read from server
int next = inFromServer.read();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (next > -1) {
if (delimiter != next) {
bos.write(next);
}
next = inFromServer.read();
if (delimiter == next) {
System.out.println(new String(bos.toByteArray()));
count++;
if (count == 1 || count == 2) {
break;
}
bos = new ByteArrayOutputStream();
}
}
if (count == 2) {
close();
}
}
void close() throws IOException {
socket.close();
}
}