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

ch.squaredesk.nova.comm.jms.JmsObjectRepository Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) Squaredesk GmbH and Oliver Dotzauer.
 *
 * This program is distributed under the squaredesk open source license. See the LICENSE file
 * distributed with this work for additional information regarding copyright ownership. You may also
 * obtain a copy of the license at
 *
 *   https://squaredesk.ch/license/oss/LICENSE
 */

package ch.squaredesk.nova.comm.jms;

import io.reactivex.Observable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jms.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

class JmsObjectRepository {
    private final Logger logger = LoggerFactory.getLogger(JmsObjectRepository.class);

    private final Map mapDestinationIdToMessageProducer = new ConcurrentHashMap<>();

    private Session producerSession;
    private Session consumerSession;
    private Destination tempQueue;

    private final Connection connection;
    private final JmsSessionDescriptor producerSessionDescriptor;
    private final JmsSessionDescriptor consumerSessionDescriptor;
    private final Function destinationIdGenerator;

    JmsObjectRepository(Connection connection,
                        JmsSessionDescriptor producerSessionDescriptor,
                        JmsSessionDescriptor consumerSessionDescriptor,
                        Function destinationIdGenerator) {
        this.connection = connection;
        this.producerSessionDescriptor = producerSessionDescriptor;
        this.consumerSessionDescriptor = consumerSessionDescriptor;
        this.destinationIdGenerator = destinationIdGenerator;
    }

    Destination getPrivateTempQueue() {
        if (tempQueue == null) {
            try {
                tempQueue = consumerSession.createTemporaryQueue();
            } catch (JMSException e) {
                throw new RuntimeException("Unable to create temp queue", e);
            }
        }
        return tempQueue;
    }


    MessageConsumer createMessageConsumer(Destination destination) throws JMSException {
        return consumerSession.createConsumer(destination);
    }

    String idFor (Destination destination) {
        return destinationIdGenerator.apply(destination);
    }

    void destroyConsumer(MessageConsumer consumer) {
        // we defer the closing of the MessageProducer (for the magical amount of 1 second"
        // because we ran into issues (which we do not understand at all) when we close a consumer
        // and very quickly afterwards create a new consumer for the same destination. This is a common
        // scenario during testing. In such a case it happened, that the new consumer never returned any
        // messages. Our theory is that for some reason the ActiveMQ broker runs into timing issues. We
        // do not have an explanation for what happens, but we saw, that if we delay the closing of the
        // no longer needed consumer, we did not experience any problems.
        Observable.timer(1, TimeUnit.SECONDS)
                .subscribe(x -> {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        consumer.close();
                    } catch (Exception e) {
                        // noop, we did our best
                    }
                });
    }


    TextMessage createTextMessage() throws JMSException {
        return producerSession.createTextMessage();
    }

    MessageProducer createMessageProducer(Destination destination) {
        String destinationId = destinationIdGenerator.apply(destination);
        return mapDestinationIdToMessageProducer.computeIfAbsent(destinationId,
                key -> {
                    try {
                        return producerSession.createProducer(destination);
                    } catch (JMSException e) {
                        throw new RuntimeException(e);
                    }
                });
    }


    void start() throws JMSException {
        connection.start();
        logger.debug("Creating producer session with the following settings: {}", producerSessionDescriptor);
        this.producerSession = connection.createSession(producerSessionDescriptor.transacted, producerSessionDescriptor.acknowledgeMode);
        logger.debug("Creating consumer session with the following settings: {}", consumerSessionDescriptor);
        this.consumerSession = connection.createSession(consumerSessionDescriptor.transacted, consumerSessionDescriptor.acknowledgeMode);
    }

    void shutdown() {
        mapDestinationIdToMessageProducer.forEach((key, value) -> {
            try {
                value.close();
            } catch (Exception e) {
                logger.warn("Unable to close producer for destination " + key, e);
            }
        });
        mapDestinationIdToMessageProducer.clear();
        try {
            consumerSession.close();
        } catch (Exception e) {
            logger.warn("Unable to close producer session", e);
        }
        try {
            producerSession.close();
        } catch (Exception e) {
            logger.warn("Unable to close producer session", e);
        }
        try {
            connection.close();
        } catch (Exception e) {
            logger.warn("Unable to close connection", e);
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy