Apache Camel: How to test for instance of Set<CustomObject>

1.1k views Asked by At

Does anyone know how to test for different types of Collection in a route?

// This processor returns a Collection of 2 Sets
// 1. Set<GoodMessage>
// 2. Set<BadMessage>
.process(new MyGoodBadMessageProcessor())
// Split the result List
.split(body()).choice()
    // How do you test for a Set<GoodMessage>??
    .when(body().isInstanceOf(Set<GoodMessage>)
        .to("direct:good")
    .otherwise()
        .to("direct:bad")
.endChoice()

Background: (In case someone can see a better way of doing this) I have a Processor that currently works as follows:

@Override
public void process(Exchange exchange) throws Exception {
    Message message = exchange.getIn();
    Set<UnknownMessage> unknownMessages = message.getBody(Set.class);
    Set<GoodMessage> goodMessages = new HashSet<GoodMessage>();

    for(UnknownMessage msg: unknownMessages) {
        // Simplified logic here
        if (msg.isGood()) {
            goodMessages.add(msg.getGoodMessage());
        }
    }

    message.setBody(goodMessages);
}

I'd like to update this as to now include the BadMessage(s) for reporting:

@Override
public void process(Exchange exchange) throws Exception {
    Message message = exchange.getIn();
    Set<UnknownMessage> unknownMessages = message.getBody(Set.class);
    Set<GoodMessage> goodMessages = new HashSet<GoodMessage>();
    Set<BadMessage> badMessages = new HashSet<BadMessage>();

    List result = new ArrayList();

    for(UnknownMessage msg: unknownMessages) {
        // Simplified logic here
        if (msg.isGood()) {
            goodMessages.add(msg.getGoodMessage());
        } else {
            badMessages.add(msg.getBadMessage());
        }
    }

    result.add(goodMessages)
    result.add(badMessages)
    message.setBody(result);
}
2

There are 2 answers

0
Andy Longwill On BEST ANSWER

The following Predicate would work, although might give incorrect results when the Set is empty :/

Public class IsGoodMessage implements Predicate {
    @Override
    public boolean matches(Exchange exchange) {
        Message message = exchange.getIn();
        Set unknownSet = message.getBody(Set.class);
        for (Object o : unknownSet) {
            if (o instanceof GoodMessage) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }
}

This helped: How do I find out what type each object is in a ArrayList<Object>?

UPDATE: After some further reading, a better way to do this is to use a Header/Property to help distinguish the message type.

STEP 1: Update Processor to produce a Map that identifies different message types.

"GOOD_MSGS" -> List<GoodMessage>
"BAD_MSGS" -> List<BadMessage>

STEP 2: Create a splitter bean that splits this Map and then creates a header using the key of Map from the previous step. (see "splitMessage" here http://camel.apache.org/splitter.html)

STEP 3: In the route use these headers to route the messages accordingly

0
6ton On

You cannot get the type of collection in this way (nothing to do with camel). The way you've updated your process method does not need creating a different end point for bad messages.

One possible way to send this to a different end point based on message type is add a processor before the choice which inspects the type of the message and adds a header. Your choice statement can then work based on this header.