Code review comment: The keySet method of org.springframework.messaging.MessageHeaders returns an unmodified Set. I have updated the copyHeaders as a map and use the putAll API.

Code before review:
protected void setCustomHeaders(MessageHeaders headers, ServiceBusMessage message) {
Set<String> copyHeaders = new HashSet<String>();
headers.forEach((key, value) -> {
copyHeaders.add(key);
});
getStringHeader(headers, copyHeaders, MessageHeaders.ID).ifPresent(message::setMessageId);
getStringHeader(headers, copyHeaders, MessageHeaders.CONTENT_TYPE).ifPresent(message::setContentType);
getStringHeader(headers, copyHeaders, MessageHeaders.REPLY_CHANNEL).ifPresent(message::setReplyTo);
getStringHeader(headers, copyHeaders, AzureHeaders.RAW_ID).ifPresent(message::setMessageId);
Optional.of(AzureHeaders.SCHEDULED_ENQUEUE_MESSAGE)
.filter(copyHeaders::remove)
.map(key -> headers.get(key, Integer.class))
.map(Duration::ofMillis)
.map(Instant.now()::plus)
.map((ins) -> OffsetDateTime.ofInstant(ins, ZoneId.systemDefault()))
.ifPresent(message::setScheduledEnqueueTime);
getStringHeader(headers, copyHeaders, MESSAGE_ID).ifPresent(message::setMessageId);
Optional.of(TIME_TO_LIVE)
.filter(copyHeaders::remove)
.map(key -> headers.get(key, Duration.class))
.ifPresent(message::setTimeToLive);
Optional.of(SCHEDULED_ENQUEUE_TIME)
.filter(copyHeaders::remove)
.map(key -> headers.get(key, Instant.class))
.map((ins) -> OffsetDateTime.ofInstant(ins, ZoneId.systemDefault()))
.ifPresent(message::setScheduledEnqueueTime);
getStringHeader(headers, copyHeaders, SESSION_ID).ifPresent(message::setSessionId);
getStringHeader(headers, copyHeaders, CORRELATION_ID).ifPresent(message::setCorrelationId);
getStringHeader(headers, copyHeaders, TO).ifPresent(message::setTo);
getStringHeader(headers, copyHeaders, REPLY_TO_SESSION_ID).ifPresent(message::setReplyToSessionId);
getStringHeader(headers, copyHeaders, PARTITION_KEY).ifPresent(message::setPartitionKey);
copyHeaders.forEach(key -> {
message.getApplicationProperties().put(key, headers.get(key).toString());
});
}

Line under review: });

Code after addressing the review:
protected void setCustomHeaders(MessageHeaders headers, ServiceBusMessage message) {
Map<String, Object> copySpringMessageHeaders = new HashMap<String, Object>();
copySpringMessageHeaders.putAll(headers);
getAndRemove(copySpringMessageHeaders, MessageHeaders.ID, UUID.class)
.ifPresent(val -> message.setMessageId(val.toString()));
getAndRemove(copySpringMessageHeaders, MessageHeaders.CONTENT_TYPE).ifPresent(message::setContentType);
getAndRemove(copySpringMessageHeaders, MessageHeaders.REPLY_CHANNEL).ifPresent(message::setReplyTo);
getAndRemove(copySpringMessageHeaders, AzureHeaders.RAW_ID).ifPresent(val -> {
message.setMessageId(val);
logOverriddenHeaders(AzureHeaders.RAW_ID, MessageHeaders.ID, headers);
});
getAndRemove(copySpringMessageHeaders, AzureHeaders.SCHEDULED_ENQUEUE_MESSAGE, Integer.class)
.map(Duration::ofMillis)
.map(Instant.now()::plus)
.map((ins) -> OffsetDateTime.ofInstant(ins, ZoneId.systemDefault()))
.ifPresent(message::setScheduledEnqueueTime);
getAndRemove(copySpringMessageHeaders, MESSAGE_ID).ifPresent(val -> {
message.setMessageId(val);
if (!logOverriddenHeaders(MESSAGE_ID, AzureHeaders.RAW_ID, headers)) {
logOverriddenHeaders(MESSAGE_ID, MessageHeaders.ID, headers);
}
});
getAndRemove(copySpringMessageHeaders, TIME_TO_LIVE, Duration.class).ifPresent(message::setTimeToLive);
getAndRemove(copySpringMessageHeaders, SCHEDULED_ENQUEUE_TIME, Instant.class)
.map((ins) -> OffsetDateTime.ofInstant(ins, ZoneId.systemDefault()))
.ifPresent(val -> {
message.setScheduledEnqueueTime(val);
logOverriddenHeaders(SCHEDULED_ENQUEUE_TIME, AzureHeaders.SCHEDULED_ENQUEUE_MESSAGE, headers);
});
getAndRemove(copySpringMessageHeaders, SESSION_ID).ifPresent(message::setSessionId);
getAndRemove(copySpringMessageHeaders, CORRELATION_ID).ifPresent(message::setCorrelationId);
getAndRemove(copySpringMessageHeaders, TO).ifPresent(message::setTo);
getAndRemove(copySpringMessageHeaders, REPLY_TO_SESSION_ID).ifPresent(message::setReplyToSessionId);
getAndRemove(copySpringMessageHeaders, PARTITION_KEY).ifPresent(message::setPartitionKey);
copySpringMessageHeaders.forEach((key, value) -> {
message.getApplicationProperties().put(key, value.toString());
});
}