2

So following this question (how to plug a TCP-IP client server in a spring MVC application), I was successfully able to wire a Gateway into my Spring REST controller. However, I'm confused as to where to go next. Here's what I'm trying to accomplish:

1) When a certain route is hit with a POST request, open a connection to a certain IP (or work with a connection that's already open with this IP) passed from the POST and send a message.

@RequestMethod(value = '/sendTcpMessage', method=RequestMethod.POST)
public void sendTcpMessage(@RequestParam(value="ipAddress", required=true) String ipAddress,
                           @RequestParam(value="message", required=true) String message) {

//send the message contained in the 'message' variable to the IP address located 
//at 'ipAddress' - how do I do this?

}

2) I also need my Spring backend to listen to TCP "messages" passed to it, and store them in a buffer. My Javascript will call a route every 5 seconds or so and read the information out of the buffer.

Here is my controller code:

@Controller
public class HomeController {

    @Resource(name = "userDaoImpl")
    private UserDAO userDao;
    @Resource(name = "receiveTcp")
    private ReceiveTcp tcpMessageReceiver;
    @Autowired
    SimpleGateway gw;

    String tcpBuffer[] = new String[100];

    @RequestMapping(value="/")
    public String home() {
        return "homepage";
    }

    @RequestMapping(value = "/checkTcpBuffer", method=RequestMethod.POST)
    public String[] passTcpBuffer() {
        return tcpMessageReceiver.transferBuffer();
    }

}

root-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
                        http://www.springframework.org/schema/integration/ http://www.springframework.org/schema/integration/spring-integration.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->
<int:gateway id="gw"
   service-interface="net.codejava.spring.interfaces.SimpleGateway"
   default-request-channel="input"/>

<bean id="javaSerializer"
      class="org.springframework.core.serializer.DefaultSerializer"/>
<bean id="javaDeserializer"
      class="org.springframework.core.serializer.DefaultDeserializer"/>

<int-ip:tcp-connection-factory id="server"
    type="server"
    port="8081"
    deserializer="javaDeserializer"
    serializer="javaSerializer"
    using-nio="true"
    single-use="true"/>

<int-ip:tcp-connection-factory id="client"
    type="client"
    host="localhost"
    port="8081"
    single-use="true"
    so-timeout="10000"
    deserializer="javaDeserializer"
    serializer="javaSerializer"/>

    <int:channel id="input" />

    <int:channel id="replies">
        <int:queue/>
    </int:channel>

    <int-ip:tcp-outbound-channel-adapter id="outboundClient"
    channel="input"
    connection-factory="client"/>

    <int-ip:tcp-inbound-channel-adapter id="inboundClient"
    channel="replies"
    connection-factory="client"/>

    <int-ip:tcp-inbound-channel-adapter id="inboundServer"
    channel="loop"
    connection-factory="server"/>

    <int-ip:tcp-outbound-channel-adapter id="outboundServer"
    channel="loop"
    connection-factory="server"/>

    <int:service-activator input-channel="input" ref="receiveTcp" method = "saveValue"/>

</beans>

ReceiveTcp.java

@Component(value = "receiveTcp")
public class ReceiveTcp {

    String buf[] = new String[100];
    int currentPosition = 0;

    @ServiceActivator
    public void saveValue(String value){
        System.out.println(value);
        buf[currentPosition] = value;
        currentPosition++;
    }

    public String[] transferBuffer() {
        String tempBuf[] = new String[100];
        tempBuf = buf;
        buf = new String[100];

        return tempBuf;
    }
}

How can I resolve these issues?

Community
  • 1
  • 1
kibowki
  • 4,206
  • 16
  • 48
  • 74

2 Answers2

1

You need to use a ResponseEntity. See this answer. A tcp connection is a 2-way connection so if your method returns the response instead of void it automatically sends it back to the ip which issued you the request. You don't have to manually do that.

Community
  • 1
  • 1
Abe
  • 8,623
  • 10
  • 50
  • 74
0

See the tcp-client-server sample. It uses TCP gateways (request/reply). For your situation you will likely want to use one-way channel adapters instead.

gateway(with void return) -> tcp-outbound-channel-adapter

and

tcp-inbound-channel-adapter -> service-activator

(where the service activator invokes a POJO that saves the inbound messages in your "buffer", probably keyed by connectionId - obtained from the message header).

Inject the gateway and POJO referenced by the service activator into your controller so you can (a) send messages and (b) empty the "buffer".

You can also listen for TcpConnectionEvents so you can detect if a connection is lost.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Hi @GaryRussell, thanks once again for your answer. I'm very new to both Spring and working with TCP, so excuse novice mistakes and try to be patient with me :). I have modified my question and attempted to implement what you have instructed - does this look correct? Also, would sending a message be as simple as calling `gw.send("message");`? I was looking through some documentation and saw people sending information like that. – kibowki Nov 14 '14 at 23:18
  • Hi Gary, I have a question about if we have to send custom java object not string from simple gateway somethiung like - send(obj) then what we have to do. I tried ur example, with string it is working but will custom hava object it is not. Can you please let me know what changes i have to make. – RCS Feb 26 '16 at 12:06
  • It's better to ask a new question rather than comment on an existing one. You can't send arbitrary Java objects over TCP. If your objects are `Serializable` you can use a [DefaultSerializer - see the documentation](http://docs.spring.io/spring-integration/reference/html/ip.html#connection-factories). If not, you need to transform your objects to/from something that is transportable, such as JSON. – Gary Russell Feb 26 '16 at 13:51