I am using Spring Integration Filter to enforce some validation logic on incoming message. The result of this validation needs to be sent back to Messaging Gateway caller in order to inform what exactly is wrong with the request.
So far I have explored two options:
throwExceptionOnRejection = "true"
in Filter annotation
This throws an exception back to the caller but its content is very generic and I cannot find a way to customize it:
detailMessage = "message has been rejected in filter: bean 'validationFilter.requestValidation.filter.handler' for component 'validationFilter.requestValidation.filter'"
Is it possible to customize thrown Exception to include the business reason behind it?
Configuration
Gateway
@MessagingGateway( name="processApiGateway", defaultRequestChannel = "inboundGatewayChannel")
public interface ProcessApiGateway {
@Gateway
Response getTransactions(Message<ServiceRequest> payload);
}
Filter
@Filter(inputChannel="inboundGatewayChannel", throwExceptionOnRejection = "true")
public boolean requestValidation(Message<ServiceRequest> message) {
try {
LocalDate fromDate = LocalDate.parse(message.getPayload().getFromDate());
LocalDate toDate = LocalDate.parse(message.getPayload().getToDate());
return (Period.between(fromDate, toDate)).getMonths() <= 1;
}
catch (DateTimeParseException ex) {
return false;
}
}
Channel
@Bean
public MessageChannel inboundGatewayChannel(@Qualifier("taskExecutor")TaskExecutor taskExecutor) {
return new ExecutorChannel(taskExecutor);
- Discard channel usage
This works well, but it feels like that exactly the same validation logic needs to be invoked twice. First time within a Filter method itself to determine if the message needs to be discarded and then the second time within Service Activator in order to process discarded message and understand what it's wrong with it so that appropriate reply can be generated to caller (as far I understand discarded message cannot be modified prior returning it from Filter).
Configuration
Filter
@Filter(inputChannel="inboundGatewayChannel", discardChannel = "filterDiscardChannel")
public boolean requestValidation(Message<ServiceRequest> message) {
try {
LocalDate fromDate = LocalDate.parse(message.getPayload().getFromDate());
LocalDate toDate = LocalDate.parse(message.getPayload().getToDate());
return (Period.between(fromDate, toDate)).getMonths() <= 1;
}
catch (DateTimeParseException ex) {
return false;
}
}
Service Activator
@Service
public class ValidationServiceActivator {
@ServiceActivator(inputChannel = "filterDiscardChannel")
public Response handleDiscardMessage(Message<ServiceRequest> message) {
//the same logic to validate discarded message
}
}
Discard Channel
@Bean public MessageChannel filterDiscardChannel() { return new PublishSubscribeChannel(); }
Question
What is the best approach to reject incoming message based on set of business rules and notify the caller about specific reason behind it?