Fixed the problem that the connection factory name of TcpConnectionOpenEvent issued by TcpConnection that set the interceptor becomes unknown.

Confirmation environment

What kind of problem?

Rough TCP / IP communication mechanism

Spring Integration supports TCP / IP communication, and TcpIn / OutboundGateway and ʻIn / OutboundChannelAdapter are prepared as communication windows, and each is associated with ConnectionFactory. When communication is required, the contact Gateway or ʻAdapter creates a TcpConnection instance from the ConnectionFactory and communicates.

What is an interceptor?

If you want to insert some processing such as log output when communicating, specify the TcpConnectionInterceptorFactory class that returns an instance of the class that inherits TcpConnectionInterceptorSupport in the ʻInterceptorFactoryChain property of ConnectionFactory`. The following is an implementation example.

Class that inherits TcpConnectionInterceptorSupport


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorSupport;
import org.springframework.messaging.Message;

public class SimpleInterceptor extends TcpConnectionInterceptorSupport {

	private static final Logger logger = LoggerFactory.getLogger(SimpleInterceptor.class);
	
	public SimpleInterceptor(ApplicationEventPublisher publisher) {
		super(publisher);
	}

	@Override
	public void send(Message<?> message) throws Exception {
		//Insert log output processing before sending a message
		logger.debug("send message via interceptor");
		super.send(message);
	}
}

TcpConnectionInterceptorFactory returns an instance of a class that inherits TcpConnectionInterceptorSupport


import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactory;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorSupport;

public class SimpleInterceptorFactory extends ApplicationObjectSupport implements TcpConnectionInterceptorFactory {

	public SimpleInterceptorFactory() {
	}

	@Override
	public TcpConnectionInterceptorSupport getInterceptor() {
		return new SimpleInterceptor(getApplicationContext());
	}
}

bean definition file


<int-ip:tcp-connection-factory id="client1"
	type="client" host="localhost" port="${availableServerSocket1}"
	single-use="true" interceptor-factory-chain="interceptorFactoryChain" />
<bean id="interceptorFactoryChain"
	class="org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain">
	<property name="interceptors">
		<array>
			<bean
				class="com.neriudon.example.tcp.interceptor.SimpleInterceptorFactory" />
		</array>
	</property>
</bean>

What's the problem?

TcpConnectionOpenEvent is issued when ConnectionFactory generates TcpConnection and the connection is established at the Socket level, but if the interceptor is set in ConnectionFactory, the connectionfactoryname property is initially set. It remains the value ʻunknown`. The following is a comparison of the log output results when the interceptor is set and when it is not set.

When an interceptor is set
11:58:32.397 [main] DEBUG com.neriudon.example.tcp.listener.TcpConnectionEventsListener - ★OPEN★ TcpConnectionOpenEvent [source=SimpleInterceptor:null], [factory=unknown, connectionId=localhost:50001:58459:aa1f25b0-570e-4631-8477-33a19f1bb6ba] **OPENED**
If no interceptor is set
11:58:32.434 [main] DEBUG com.neriudon.example.tcp.listener.TcpConnectionEventsListener - ★OPEN★ TcpConnectionOpenEvent [source=TcpNetConnection:localhost:50002:58460:a92051dd-9003-4563-be59-3675dee3112d], [factory=client2, connectionId=localhost:50002:58460:a92051dd-9003-4563-be59-3675dee3112d] **OPENED**

Why this problem occurs and what to do about it

This is because there is no process to set ConnectionFactoryName in the TcpConnectionInterceptorSupport class. However, since the information of ConnectionFactory is possessed by TcpConnection that actually communicates, if TcpConnectionInterceptorSupport returnsConnectionFactoryName of TcpConnection when returningConnectionFactoryName: ok_hand :. Please refer to the PR link below for details. By the way, other TcpConnectionEvents are not a problem because they were originally designed so that TcpConnectionInterceptorSupport calls the processing of TcpConnection.

What is the impact of this issue?

Almost none: stuck_out_tongue_winking_eye :. The TcpConnectionInterceptorSupport was incorporated into master in March 2016, and no bugs have been reported since then, and the TcpConnectionOpenEvent itself is the Spring Integration document. /spring-integration/docs/4.3.13.RELEASE/reference/html/ip.html#tcp-events) is also shallow, so this issue shouldn't have a serious impact on your project.

When will it be fixed?

I don't know when it will be released, but as far as I can see in JIRA, it will be fixed in the following 5.0.1, 4.3.14. As of January 15, 2018, PR has been issued and will be merged soon.

How did you come to post this article?

That's because I asked stackoverflow about this: stuck_out_tongue_closed_eyes :. In the Spring Integration project, it is a rule to ask questions about usage and specifications by stack overflow with the spring-integration tag. I couldn't tell if it was a bug or a specification, so I created a sample app and presented the conditions and logs that would occur. Answered that it was a bug. However, I wasn't able to report a bug to OSS for the first time because a person inside had submitted a vote to JIRA while I was waiting: confounded :.

1/30 postscript: Incorporating this fix 4.3.14.RELEASE and 5.0.1.RELEASE (: //github.com/spring-projects/spring-integration/releases/tag/v5.0.1.RELEASE) has been released: v :.

Recommended Posts

Fixed the problem that the connection factory name of TcpConnectionOpenEvent issued by TcpConnection that set the interceptor becomes unknown.
Problem that the attribute of User model becomes nil in ActionMailer