0

I am trying to validate message with Apache Camel (ver 2.10.4) that is sent to a Virtual Topic in FuseESB (based on Apache ServiceMix, ver 7.1.0), using validator:xsd (message is XML in TextMessage), and when it fails the validation, I want to redirect the message to another topic, and stop processing, so do not send it to usual consumers. Because consumers will fail with invalid message.

I wanted to do validation with routing, so validating once, instead of doing it on multiple consumers.

Is this possible with Camel? and what would be the syntax?

my current approach is like this:

static final String ACTIVEMQ_TOPIC_PREFIX = "activemq:topic:";
static final String ACTIVEMQ_CONSUMER_PREFIX = "activemq:queue:Consumer.*.";

static final String TOPIC_ORDER_CREATED = "VirtualTopic.order.created";
static final String TOPIC_ORDER_CREATED_ERROR = 
                                          "VirtualTopic.order.created.error";

static final String DIRECT_ORDER_CREATED_ERROR = "direct:orderCreatedError";


from(DIRECT_ORDER_CREATED_ERROR)
    .to(ACTIVEMQ_TOPIC_PREFIX + TOPIC_ORDER_CREATED_ERROR)
    .log("Message sent to " + TOPIC_ORDER_CREATED_ERROR);

// validate order.created topic message 
// before sending to consumer queues.
from(ACTIVEMQ_TOPIC_PREFIX + TOPIC_ORDER_CREATED) 
    .errorHandler(deadLetterChannel(DIRECT_ORDER_CREATED_ERROR))
    .choice() // validation is enabled with property
        .when(simple("${properties:" + PROP_VALIDATION_ENABLED + "} == true"))
            .log("Validating order created body")
            .to("validator:xsd/myxsd.xsd") // validate against xsd
            .onException(ValidationException.class)
                .handled(true) 
                .maximumRedeliveries(0)
                .useOriginalMessage()
                // if invalid send to error topic
                .to(DIRECT_ORDER_CREATED_ERROR)
                .stop()
            .end()
    .end()
    .to(ACTIVEMQ_CONSUMER_PREFIX + TOPIC_ORDER_CREATED)
    .log("Message sent to " + TOPIC_ORDER_CREATED);

I see "Validating order created body" and "Message sent to VirtualTopic.order.created.error" in the logs. On webconsole, I see a message enqueued in error topic for one message of main topic.

The problem is the consumer of VirtualTopic.order.created still gets the invalid message

Could you please help me to find the right syntax to intercept message before it goes to consumers of VirtualTopic?

Thanks

srex
  • 121
  • 1
  • 7

1 Answers1

0

You can just use the deadLetterChannel, and have it use the original message, and then any errors gets handled and moved to the DLQ.

from(ACTIVEMQ_TOPIC_PREFIX + TOPIC_ORDER_CREATED) 
.errorHandler(deadLetterChannel(DIRECT_ORDER_CREATED_ERROR).useOriginalMessage())
.choice() // validation is enabled with property
    .when(simple("${properties:" + PROP_VALIDATION_ENABLED + "} == true"))
        .log("Validating order created body")
        .to("validator:xsd/myxsd.xsd") // validate against xsd
.end()
.to(ACTIVEMQ_CONSUMER_PREFIX + TOPIC_ORDER_CREATED)
.log("Message sent to " + TOPIC_ORDER_CREATED);

Also if you are using onException in the route, then you should put that in the top of the route, not in the middle.

Claus Ibsen
  • 56,060
  • 7
  • 50
  • 65
  • Thanks @ClausIbsen for response. The consumer does not get the invalid message but now i have another problem, the valid messages are queued to `Consumer.*.VirtualTopic.order.created` I am using VirtualTopic and I want to route message to Consumers of this topic if the message is valid. Do I use wildcard wrong? because the message is not queued in consumer. – srex Apr 25 '13 at 17:48