user3919727
user3919727

Reputation: 343

Ignore message from a MQ topic from a specific channel

There is a IBM MQ topic which accepts two types of messages Orders and Shipments. I have a Springboot subscriber app which is interested in subscribing only the Shipment message type.

Below is how I am routing the channel. If the inbound message is neither of above types it will be thrown to errorChannel that I have. Here if I do not have orderChannel app will throw an error saying no proper channel for the inbound message.

How do I silently ignore the messages of type order here?

@Bean
@ServiceActivator(inputChannel = "routerChannel")
public HeaderValueRouter router() throws Exception {
  HeaderValueRouter router = new HeaderValueRouter(messageType);
  router.setChannelMapping(shipment, "shipmentChannel");
  router.setChannelMapping(order, "orderChannel");
  router.setDefaultOutputChannel(invalidHeaderValueChannel);
  return router;
}

Currently I have the below code snippet which I need to have just to avoid the error when there was a Order message.

@ServiceActivator(inputChannel = "orderChannel")
public void getInboundOrderMessage(Message<?> message) throws Exception {

    logger.info("Inbound Order message...");
    String payload = (String) message.getPayload();
    logger.info("Order Header: {}, payload: \n{}", pMessage.getHeaders(), payload);
}

Below is how I have the MsgDrivenChannelAdapter defined

@MessageEndpoint
public class MsgDrivenChannelAdapter {

    private AbstractMessageListenerContainer messageListenerContainer;
    private DirectChannel inboundErrorChannel;
    private DirectChannel routerChannel;

    public MsgDrivenChannelAdapter(AbstractMessageListenerContainer pMessageListenerContainer,
                                   DirectChannel pInboundErrorChannel,
                                   DirectChannel pRouterChannel) {
        this.messageListenerContainer = pMessageListenerContainer;
        this.inboundErrorChannel = pInboundErrorChannel;
        this.routerChannel = pRouterChannel;
    }

    @Bean
    public IntegrationFlow jmsInboundFlow() throws Exception {
        return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(messageListenerContainer)
                .errorChannel(inboundErrorChannel))
                .channel(routerChannel)
                .get();
    }
}

Is there anyway I can avoid this? thanks in advance

Upvotes: 0

Views: 356

Answers (2)

user3919727
user3919727

Reputation: 343

This is how I did it to make it work as I wanted. I used filter to fetch only the particular message type

@Bean
public IntegrationFlow jmsInboundFlow() throws Exception {
return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(messageListenerContainer)
        .errorChannel(inboundErrorChannel))
        .filter(Message.class, m -> m.getHeaders().get("message_type").equals("shipment"))
        .channel(routerChannel)
        .get();
}

Upvotes: 0

Artem Bilan
Artem Bilan

Reputation: 121552

See this option on the router:

/**
 * When true (default), if a resolved channel key does not exist in the channel map,
 * the key itself is used as the channel name, which we will attempt to resolve to a
 * channel. Set to false to disable this feature. This could be useful to prevent
 * malicious actors from generating a message that could cause the message to be
 * routed to an unexpected channel, such as one upstream of the router, which would
 * cause a stack overflow.
 * @param channelKeyFallback false to disable the fall back.
 * @since 5.2
 */
public void setChannelKeyFallback(boolean channelKeyFallback) {

So, it does not fallback to the order as a channel name.

Then it will return as null from the mapping and the logic goes like this:

    if (!sent) {
        getDefaultOutputChannel();
        if (this.defaultOutputChannel != null) {
            this.messagingTemplate.send(this.defaultOutputChannel, message);
        }
        else {
            throw new MessageDeliveryException(message, "No channel resolved by router '" + this
                    + "' and no 'defaultOutputChannel' defined.");
        }
    }

If you want just to ignore it and don't want to have that MessageDeliveryException, configure a defaultOutputChannel as a nullChannel.

But better to consider a messageSelector for the listener container, so it does not pull messages from a topic which it is not interested in.

Upvotes: 1

Related Questions