
fi.evolver.basics.spring.util.MessageChainUtils Maven / Gradle / Ivy
package fi.evolver.basics.spring.util;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import fi.evolver.basics.spring.common.SequenceRepository;
import fi.evolver.utils.ContextUtils;
import fi.evolver.utils.ContextUtils.ContextCloser;
import fi.evolver.utils.TagUtils.Tag;
import fi.evolver.utils.attribute.ContextAttribute;
import fi.evolver.utils.attribute.Slf4jMdcAttribute;
import fi.evolver.utils.attribute.TypedAttribute;
@Lazy(false)
@Component
public class MessageChainUtils {
private static final Logger LOG = LoggerFactory.getLogger(MessageChainUtils.class);
public static final MessageChainIdTag TAG = new MessageChainIdTag();
public static final String MESSAGE_CHAIN_ID = "MessageChainId";
private static final TypedAttribute CONTEXT_MESSAGE_CHAIN_ID = new ContextAttribute<>(MESSAGE_CHAIN_ID, Long.class);
private static final TypedAttribute MDC_MESSAGE_CHAIN_ID = new Slf4jMdcAttribute(MESSAGE_CHAIN_ID);
private static SequenceRepository sequenceRepository;
private MessageChainUtils() { }
/**
* Ensures we have an active context and starts a new message chain within that.
*
* @return A closer for the message chain and the context if created by this method.
*/
public static MessageChain startMessageChain() {
return startMessageChain(null);
}
/**
* Ensures we have an active context and starts a new message chain within that with the given id.
*
* @param messageChainId The if of the message chain to start.
* @return A closer for the message chain and the context if created by this method.
*/
public static MessageChain startMessageChain(Long messageChainId) {
LOG.trace("{}: START Message chain", Thread.currentThread().getId());
MessageChain result = new MessageChain(ContextUtils.ensureContext());
setMessageChainId(messageChainId);
return result;
}
/**
* Gets the current message chain id or generates a new one if missing.
*
* @return The current message chain id.
*/
public static long getMessageChainId() {
if (!ContextUtils.withinContext()) {
LOG.error("Trying to get message chain id without a context");
return -1L;
}
Long result = CONTEXT_MESSAGE_CHAIN_ID.get().orElse(null);
if (result == null) {
if (sequenceRepository == null) {
LOG.error("Sequence repository has not been set, defaulting to -1");
return -1L;
}
result = sequenceRepository.getNextValue(MESSAGE_CHAIN_ID);
setMessageChainId(result);
}
if (LOG.isTraceEnabled())
LOG.trace("{}: Message chain ID == {}", Thread.currentThread().getId(), result);
return result;
}
/**
* Do we already have a message chain initialized?
*
* @return Are we within a message chain or not.
*/
public static boolean isMessageChainOpen() {
return CONTEXT_MESSAGE_CHAIN_ID.get().isPresent();
}
private static void setMessageChainId(Long messageChainId) {
if (LOG.isTraceEnabled())
LOG.trace("{}: Message chain ID {} => {}", Thread.currentThread().getId(), CONTEXT_MESSAGE_CHAIN_ID.get().orElse(null), messageChainId);
if (messageChainId == null) {
CONTEXT_MESSAGE_CHAIN_ID.remove();
MDC_MESSAGE_CHAIN_ID.remove();
}
else {
CONTEXT_MESSAGE_CHAIN_ID.set(messageChainId);
MDC_MESSAGE_CHAIN_ID.set(messageChainId.toString());
}
}
/**
* Closes the message chain and any context started for it.
*/
public static class MessageChain implements AutoCloseable {
private final ContextCloser contextCloser;
public MessageChain(ContextCloser contextCloser) {
this.contextCloser = contextCloser;
}
@Override
public void close() {
setMessageChainId(null);
if (contextCloser != null)
contextCloser.close();
LOG.trace("{}: CLOSE Message chain", Thread.currentThread().getId());
}
}
@Autowired
public void setSequenceService(SequenceRepository sequenceRepository) {
MessageChainUtils.sequenceRepository = sequenceRepository;
}
private static class MessageChainIdTag extends Tag {
public MessageChainIdTag() {
super(Pattern.compile("@MessageChainId@", Pattern.CASE_INSENSITIVE));
}
@Override
protected String replace(String occurence) {
return String.valueOf(MessageChainUtils.getMessageChainId());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy