All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fi.evolver.basics.spring.messaging.MessagingService Maven / Gradle / Ivy

package fi.evolver.basics.spring.messaging;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import fi.evolver.basics.spring.log.LogUtils;
import fi.evolver.basics.spring.log.MessageLogService;
import fi.evolver.basics.spring.log.entity.MessageLog.Direction;
import fi.evolver.basics.spring.log.entity.MessageLogMetadata;
import fi.evolver.basics.spring.messaging.entity.Message;
import fi.evolver.basics.spring.messaging.entity.MessageData;
import fi.evolver.basics.spring.messaging.entity.MessageTargetConfig;
import fi.evolver.basics.spring.messaging.model.MessageDetails;


@Service
public class MessagingService {
	private static final Logger LOG = LoggerFactory.getLogger(MessagingService.class);

	public static final String METADATA_SPECIFIER = "Specifier";

	private final MessageLogService messageLogService;
	private final MessageRepository messageRepository;
	private final MessageTargetConfigRepository messageTargetConfigRepository;
	private final IMessageSender messageSender;

	@Value("${spring.datasource.url:?}")
	private String dbConnectionUrl;


	@Autowired
	public MessagingService(
			MessageLogService messageLogService,
			MessageRepository messageRepository,
			MessageTargetConfigRepository messageTargetConfigRepository,
			@Lazy IMessageSender messageSender) {

		this.messageLogService = messageLogService;
		this.messageRepository = messageRepository;
		this.messageTargetConfigRepository = messageTargetConfigRepository;
		this.messageSender = messageSender;
	}


	@Transactional(propagation = Propagation.REQUIRED)
	public void send(String messageType, List messages) {
		List allTargets = messageTargetConfigRepository.findAllByMessageType(messageType);
		if (allTargets.isEmpty()) {
			LOG.info("No targets were found for message type {}: SKIP {} messages", messageType, messages.size());
			return;
		}

		Map> targetsWithMessages = new TreeMap<>();

		Optional specifier = Optional.ofNullable(LogUtils.getSpecifier());

		List toSend = new ArrayList<>();
		for (MessageDetails message: messages) {
			specifier.ifPresent(s -> message.getProperties().putIfAbsent(METADATA_SPECIFIER, s));

			List targets = allTargets.stream()
					.filter(t -> t.shouldSend(message.getProperties()))
					.collect(Collectors.toList());

			if (targets.isEmpty()) {
				LOG.info("No applicable targets were found for message of type {} ({}): SKIP", messageType, message.getProperties());
				continue;
			}

			targets.forEach(t -> targetsWithMessages.computeIfAbsent(t.getId(), k -> new TreeSet<>()).add(message.getMessageGroupId()));

			MessageData messageData = message.createMessageData();
			toSend.addAll(targets.stream().map(t -> new Message(t, messageData, message.getMessageGroupId(), message.getPriority())).collect(Collectors.toList()));
		}

		if (!toSend.isEmpty()) {
			List metadata = toSend.stream().collect(Collectors.groupingBy(Message::getTargetSystem)).entrySet().stream()
					.sorted(Comparator.comparing(Map.Entry::getKey))
					.map(e -> new MessageLogMetadata(e.getKey(), Integer.toString(e.getValue().size())))
					.collect(Collectors.toList());

			messageRepository.saveAll(toSend);
			messageLogService.logMessage(
					LocalDateTime.now(),
					messageType,
					"jdbc",
					dbConnectionUrl,
					MessagingService.class.getSimpleName(),
					"DB",
					Direction.OUTBOUND,
					null,
					null,
					null,
					null,
					"OK",
					"Queued " + toSend.size() + " messages",
					metadata);

			triggerSending(targetsWithMessages);
		}
	}


	private void triggerSending(Map> targets) {
		targets.forEach((id, groups) -> groups.stream().forEach(group -> messageSender.sendPendingMessages(id, group)));
	}


	@Transactional(propagation = Propagation.REQUIRED)
	public void send(String messageType, MessageDetails message) {
		send(messageType, Collections.singletonList(message));
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy