4
votes

I am using the claim check pattern from , but I would like to have the message stored with a custom ID. This should be easy, as the message store implementations are using the incoming message header id to store the message. Is it possible to overwrite the value of the message header id using a header enricher or/and a header filter?

Message header id and the message store

The SimpleMessageStore, as well as the JdbcMessageStore, are using the incoming message ID to store the message. In the addMessage method (the example is from the SimpleMessageStore) we have:

this.idToMessage.put(message.getHeaders().getId(), message); 

To have a custom ID it should be enough to have a header enricher before claim check in, where the value of the id header is replaced with a custom value. For example:

<int:header-enricher input-channel="gateDocCheckInReqChannel" 
    output-channel="gateDocCheckInEnrichedChannel">
    <int:header name="id" expression="payload.getDocumentID()" overwrite="true" />
</int:header-enricher>
<int:claim-check-in input-channel="gateDocCheckInEnrichedChannel" 
    output-channel="gateDocCheckInReplyChannel" message-store="messageStore" />

It does not work; the message header id is not overwritten. I tried having a header filter on ID before the header enricher, but it does not work either.

Related

I found this old post on removing the headers fields that is undone by some internal logic:
http://forum.spring.io/forum/spring-projects/integration/74099-remove-header-fields
Also, there is this closed issue INT-923 on a message handler that undoes header removals.
https://jira.spring.io/browse/INT-923
It is supposed that issue INT-1135 on header filters fixes this behavior.
https://jira.spring.io/browse/INT-1135

2

2 Answers

2
votes

Actually the ID and TIMESTAMP header are read-only (MessageHeaderAccessor):

protected boolean isReadOnly(String headerName) {
    return (MessageHeaders.ID.equals(headerName) || MessageHeaders.TIMESTAMP.equals(headerName));
}

They are specified for the concrete Message, which is immutable.

Those header are designed for the internal usage in the framework and they can't be changed.

For such a use-case like yours, there is need to introduce addition businessKey and get deal with that not thinking about those interlan headers.

Since you say that you want to determine somehow a message by the ID from the store after claim-ckeck, I suggest you to consder to use MetadataStore to keep ID <-> businessKey pairs to have an ability to restore them in the future somehow.

Of course, you can try to use MutableMessageBuilder for your specific use-case:

MutableMessageBuilder.fromMessage(message)
            .setHeader(MessageHeaders.ID, UUID.randomUUID())
            .build()

But ID must be UUID anyway.

And right: HeaderFilter doesn't remove those read-only headers as well.

0
votes
I have overridden the http_requestMethod by doing as like below. The request coming is Post which I have removed from Headers and added PUT.


<int:header-filter input-channel="headerFilterChannel"
        header-names="http_requestMethod" output-channel="closeAndCloneOldTasksHeaderEnricherChannel" />

    <int:header-enricher input-channel="closeAndCloneOldTasksHeaderEnricherChannel"
        output-channel="caresToSfdc">
        <int:header name="http_requestMethod" value="PUT" />
    </int:header-enricher>

***Before Overriding Log*** 
GenericMessage [payload=com.cardinalhealth.chh.exception.model.GenericResponse@1948829c, headers={http_requestMethod=POST, replyChannel=org.springframework.messag

**After  Overriding Log :**
GenericResponse@142cd5fd, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@5710c249, http_requestMethod=PUT,