jcastaneyra jcastaneyra - 23 days ago 6
Java Question

Spring Integration enrichHeader with randomUUID

I'm a newbie with Spring Integration, using Java 7, and I had this xml configuration before moving to Spring integration DSL, and my application was working to enrich a header with a monitoring ID generated from random UUID (This was to correlate request and response for later searching in logs, maybe this could be done in a different way, don't know):

<int:chain input-channel="requestChannel" output-channel="responseChannel">
<int:header-enricher>
<int:header name="translator-monitoringId" expression="T(java.util.UUID).randomUUID()"/>
</int:header-enricher>
<int:transformer ref="customHeaderTransformerBean" method="convertToJson"/>
<int-amqp:outbound-gateway
exchange-name="translatorExchange"
amqp-template="amqpTemplate"
routing-key-expression ="headers['translatorRoutingKey']"
mapped-request-headers="translator-*"
mapped-reply-headers="translator-*"/>
</int:chain>


So, after moving to DSL, I have this:

return IntegrationFlows
.from("requestChannel")
.enrichHeaders(new Consumer<HeaderEnricherSpec>() {
@Override
public void accept(HeaderEnricherSpec t) {
t.header(Constants.MONITORING_ID, UUID.randomUUID());
}
})
.transform(customToJsonTransformer())
.handle(Amqp
.outboundGateway(rabbitTemplate())
.exchangeName(TRANSLATOR_EXCHANGE_NAME)
.routingKeyExpression(
"headers['" + Constants.TRANSLATOR_ROUTING_KEY + "']")
.mappedReplyHeaders(Constants.AMQP_CUSTOM_HEADER_FIELD_NAME_MATCH_PATTERN)
.mappedRequestHeaders(Constants.AMQP_CUSTOM_HEADER_FIELD_NAME_MATCH_PATTERN))
.route(new ResponseFromTranslatorRouterSI(jsonResponseMessageChannel(), exceptionResponseMessageChannel())).get();


Well, the thing is that random UUID is included in headers as monitoringId, but after the first execution it remains the same, it does not change with each request as was before.

Do you know if I am missing something?

Thanks for your help.

Answer

Yes, that's correct.

Let's take a look to your code one more time:

public void accept(HeaderEnricherSpec t) {
      t.header(Constants.MONITORING_ID, UUID.randomUUID());
}

So, when your UUID.randomUUID() will be evaluated? Right, just during accept() method invocation. Therefore only once.

With your XML variant you deal with expression which really evaluates for each message.

To make it working in Java DSL style you should do something similar:

 t.headerExpression(Constants.MONITORING_ID, "T(java.util.UUID).randomUUID()");

or even better like:

t.headerFunction(Constants.MONITORING_ID, 
     new Function<Message<Object>, Object>() {
           Object apply(Message<Object> message) {
               return UUID.randomUUID();
           }
     }
);