Reputation: 11
I have an external TCP server which listens on a port and once a connection is successfully made by a client, it will start pushing data(can think this as a typical publish-subscription model).Only initial request will be sent from the application to server to create the socket connection, no other requests will be sent. Server pushes the data whenever it has. The problem here is, I made a connection with the server using TCP outbound endpoint but how can I continuously listen on the socket created by my outbound to receive the data published by the server?
Upvotes: 1
Views: 702
Reputation: 440
One way to share the client socket connection to the listener would be to use a custom MessageDispatcher in the TCP outbound connector like -
<tcp:connector name="TCP2" doc:name="TCP connector"
clientSoTimeout="70000" receiveBacklog="0" receiveBufferSize="0"
sendBufferSize="0" serverSoTimeout="70000" socketSoLinger="0"
validateConnections="true" keepAlive="true" sendTcpNoDelay="true"
keepSendSocketOpen="true">
<receiver-threading-profile
maxThreadsActive="1" maxThreadsIdle="1" />
<reconnect-forever />
<service-overrides dispatcherFactory="CustomMessageDispatcherFactory"/>
</tcp:connector>
You will have a dispatcher factory class like
import org.mule.api.MuleException;
import org.mule.api.endpoint.OutboundEndpoint;
import org.mule.api.transport.MessageDispatcher;
import org.mule.transport.tcp.TcpMessageDispatcherFactory;
public class CustomMessageDispatcherFactory extends TcpMessageDispatcherFactory {
public MessageDispatcher create(OutboundEndpoint endpoint) throws MuleException
{
return new CustomMessageDispatcher(endpoint);
}
}
And a CustomMessageDispatcher.class like below -
import org.mule.api.MuleEvent;
import org.mule.api.MuleMessage;
import org.mule.api.endpoint.OutboundEndpoint;
import org.mule.api.transformer.TransformerException;
import org.mule.transport.AbstractMessageDispatcher;
import org.mule.transport.NullPayload;
import org.mule.transport.tcp.TcpConnector;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Send transformed Mule events over TCP.
*/
public class CustomMessageDispatcher extends AbstractMessageDispatcher
{
private final TcpConnector connector;
public CustomMessageDispatcher (OutboundEndpoint endpoint)
{
super(endpoint);
this.connector = (TcpConnector) endpoint.getConnector();
}
@Override
protected synchronized void doDispatch(MuleEvent event) throws Exception
{
/* Share the socket with the mule flow as a session variable */
Socket socket = connector.getSocket(endpoint);
event.getMessage().setInvocationProperty("ClientSocket", socket);
/* If you have something to be dispatched, you can use the below section of code */
try
{
dispatchToSocket(socket, event);
}
finally
{
connector.releaseSocket(socket, endpoint);
}
}
@Override
protected MuleMessage doSend(MuleEvent event) throws Exception {
// Not used since we do not do request-response for the outbound endpoint
return null;
}
}
If you are looking to listen to the same socket, you can use the same class for listening too. You can write your own implementation for the doSend() method. This method will get triggered when the endpoint is set as "request-response" and it receives the byte array and sends it back to the mule flow after assigning it as the payload. Please refer the class org.mule.transport.tcp.TcpMessageDispatcher.class for the default usage of these methods. FYI - I havent tested the above logic myself, but I have a similar implementation to send the socket object across mule flows. Hope this helps you.
Upvotes: 1