Reputation: 86747
I have the following working socket server configuration, and would like to add a handler if any exception occurs, eg inside the Deserializer
during read of the message.
Therefore I added a @ServiceActivator(inputChannel = "errorChannel")
. But the method is never invoked. Why?
@MessageEndpoint
public class SocketEndpoint {
@ServiceActivator(inputChannel = "mainChannel")
public String handleMessage(String message) {
return "normal response";
}
@ServiceActivator(inputChannel = "errorChannel")
public String handleError(MessagingException message) {
//TODO this is never invoked!
return "some error";
}
}
@Bean
public TcpInboundGateway mainGateway(
@Qualifier("tcpFactory") TcpConnectionFactoryFactoryBean factory,
@Qualifier("mainChannel") MessageChannel mainChannel,
@Qualifier("errorChannel") MessageChannel errorChannel) throws Exception {
TcpInboundGateway g = new TcpInboundGateway();
g.setConnectionFactory(factory.getObject());
g.setRequestChannel(mainChannel);
g.setErrorChannel(errorChannel);
return g;
}
@Bean
public TcpConnectionFactoryFactoryBean fact() {
TcpConnectionFactoryFactoryBean f = new TcpConnectionFactoryFactoryBean();
f.setType("server");
//....
f.setDeserializer(new MyDeserializer());
return f;
}
class MyDeserializer implements Deserializer<String> {
@Override
public String deserialize(InputStream inputStream)
throw new RuntimeException("catch me in error-channel");
}
}
Upvotes: 1
Views: 226
Reputation: 174554
throw new RuntimeException("catch me in error-channel");
It can't go to the error channel since there's no message yet (messages sent to error channels are messages that fail downstream processing).
The standard deserializers (that extend AbstractByteArraySerializer
) publish a TcpDeserializationExceptionEvent
when deserialization fails. See the ByteArrayCrLfSerializer
for an example:
public int fillToCrLf(InputStream inputStream, byte[] buffer) throws IOException {
int n = 0;
int bite;
if (logger.isDebugEnabled()) {
logger.debug("Available to read: " + inputStream.available());
}
try {
...
}
catch (SoftEndOfStreamException e) {
throw e;
}
catch (IOException e) {
publishEvent(e, buffer, n);
throw e;
}
catch (RuntimeException e) {
publishEvent(e, buffer, n);
throw e;
}
}
See the documentation. The Deserializer
needs to be a bean so that it gets an event publisher.
You can then listen for the event(s) with an ApplicationListener< TcpDeserializationExceptionEvent>
or an @EventListener
method.
Upvotes: 1