In spring integration I have a simple tcp client pipe: a gateway, a tcp outbound gateway a service activator plus an error channel. In the tcp-connection-factory there is a simple interceptor. The error channel very simple, I implemented the tcp-connection-event-inbound-channel-adapter with this filter:
- org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent.
So my error handler very simple,looks like this :
public class TcpErrorHandler {
public void onException(){
System.out.println("Exception!!! ");
}
}
It works, because when I have a Socket close Exception ( the server side I close the connection ) , the application writes "Exception!!!" to the console, but other hand, it doesn't work, when I have connection time out exception. My questions are : How do I get all most relevant exceptions for me:
- Runtime Socket close Exception
- Connection time out exception
- Other exceptions
Are there any catching mechanism ?
Here is a snipet from my bean config:
<!-- Client side -->
<int:gateway id="gw"
service-interface="hu.gmxdev.climaxreplica.service.SimpleGateway"
default-request-channel="outputchannel" />
<int-ip:tcp-connection-factory id="client"
type="client" host="localhost" port="10001" single-use="true"
so-timeout="2000" deserializer="climaxDeserializer"
interceptor-factory-chain="customInterceptorFactoryChain"/>
<int:channel id="outputchannel" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="outputchannel" reply-channel="replychannel"
connection-factory="client" request-timeout="2000" reply-timeout="2000" />
<int:service-activator input-channel="replychannel"
method="reply" ref="echoService" id="serviceactivator">
</int:service-activator>
<int:channel id="replychannel"></int:channel>
<bean id="customInterceptorFactoryChain"
class="org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain">
<property name="interceptors">
<array>
<bean class="hu.gmxdev.climaxreplica.service.CustomInterceptorFactory"/>
</array>
</property>
</bean>
<!-- Error channel -->
<int-ip:tcp-connection-event-inbound-channel-adapter id="event"
error-channel="errorChannel"
event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent" />
<int:channel id="errorChannel"></int:channel>
<int:service-activator ref="tcpErrorHandler" method="onException"
input-channel="errorChannel">
</int:service-activator>
And here is my error handler :
public class TcpErrorHandler {
@Autowired
private ApplicationContext appContext;
public void onException(TcpConnectionExceptionEvent event){
MainService mainService = appContext.getBean(MainService.class);
mainService.setSuccess(3);
System.out.println("Exception!!! ");
System.out.println(event.getCause().getMessage());
}
}
The interceptor is here :
public class CustomInterceptor extends TcpConnectionInterceptorSupport{
public CustomInterceptor () {
System.out.println("catched_constructor1");
}
public CustomInterceptor (ApplicationEventPublisher applicationEventPublisher) {
super(applicationEventPublisher);
System.out.println("catched_constructor");
}
@Override
public boolean onMessage(Message<?> message) {
System.out.println("catched_message");
return super.onMessage(message);
}
@Override
public void send(Message<?> message){
System.out.println("catched_send");
MessageHeaders mh = message.getHeaders();
try {
super.send(message);
}
catch (Exception e) {
System.out.println("catched_send_exception");
}
}
@Override
public void close() {
String id = getConnectionId();
System.out.println("catched_closed" + id);
super.close();
}
}
And my "caller" :
success = gateway.send("fooooooo");
Actually <tcp-connection-event-inbound-channel-adapter> send to the channel a Message with TcpConnectionExceptionEvent (in your case) as payload.
Therefore your subscriber (your TcpErrorHandler) can accepts TcpConnectionExceptionEvent as a method argument.
In that method you can do further logic, e.g. extract the original Exception from that IntegrationEvent.
There are several places in the IP module when TcpConnectionSupport.publishConnectionExceptionEvent is used.
If you say that you don't catch time out exception, it will great if you share the logs on the matter. I wonder which place we don't try...catch on the SocketTimeoutException...
UPDATE
<int-ip:tcp-connection-event-inbound-channel-adapter channel="events"
event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent"/>
<service-activator input-channel="events" ref="tcpErrorHandler"/>
public class TcpErrorHandler {
public void onException(TcpConnectionExceptionEvent event) {
System.out.println("Exception!!! ");
event.getCause();
....
}
}
This should work.
UPDATE2
According to your code:
try {
super.send(message);
}
catch (Exception e) {
System.out.println("catched_send_exception");
}
Don't you think that it is bad to suffocate an Exception there?
From other side: would you mind switching on DEBUG logging level for the org.springframework.integration category and share here the logs, when you are sure that your tcpErrorHandler should be invoked?
From other side try <int-ip:tcp-connection-event-inbound-channel-adapter> without event-types at all. I mean let's see, if it handle any IpIntegrationEvent.
You can define an error channel, that you provide to your inbound adapter. Here is an example:
<int:channel id="error-channel"></int:channel>
<int-ws:inbound-gateway id="gateway" error-channel="error-channel"
request-channel="in" marshaller="marshaller" unmarshaller="marshaller"
reply-channel="out" />
Now all exception that are thrown downstream will be catched by this error-channel. You can then define a service activator with this error channel as an input:
<int:service-activator input-channel="error-channel"
ref="exceptionHandler" method="handleError" output-channel="outError"></int:service-activator>
And this activator refers to a bean that defines error handling logic.
来源:https://stackoverflow.com/questions/26646963/in-spring-integration-how-do-i-catching-different-exceptions