spring artemis config

22 December 2019

spring boot에서 activemq artemis를 설정하는 방법을 알아보도록 하겠습니다.
ArtemisAutoConfiguration이 설정되어 있으면, application의 설정에 상관없이
artemis가 enable되므로 아래와 같이 autoconfiguration을 꺼주도록 합니다.

@SpringBootApplication(exclude = ArtemisAutoConfiguration.class)
그리고 아래와 같이 dependency를 추가해주도록 합니다.
 compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'

    compile group: 'org.springframework', name: 'spring-jms', version: '5.2.5.RELEASE'
    compile group: 'org.apache.activemq', name: 'artemis-jms-server', version: '2.11.0'
    compile group: 'org.apache.activemq', name: 'activemq-pool', version: '5.15.12'

    compile group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
package org.shashaka.io;

import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;

import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Session;

@Configuration
public class JmsConfig {

    public static final String QUEUE_NAME = "queue1";

    @Bean(initMethod = "start", destroyMethod = "stop")
    public ActiveMQServer activeMQServer() throws Exception {
        return ActiveMQServers.newActiveMQServer(configuration());
    }

    private org.apache.activemq.artemis.core.config.Configuration configuration() throws Exception {
        return new ConfigurationImpl()
                .setSecurityEnabled(false)
                .setJMXManagementEnabled(false)
                .setEnabledAsyncConnectionExecution(true)
                .setPersistenceEnabled(true)
                .setThreadPoolMaxSize(100)
                .setScheduledThreadPoolMaxSize(20)
                .setGlobalMaxSize(4000000)
                .setGracefulShutdownEnabled(true)
                .setGracefulShutdownTimeout(600000)
                .addQueueConfiguration(new CoreQueueConfiguration()
                        .setAddress("/queue/" + QUEUE_NAME)
                        .setName(QUEUE_NAME)
                        .setDurable(false)
                        .setRoutingType(RoutingType.ANYCAST))
                .addAcceptorConfiguration("in-vm", "vm://0");
    }


    @Bean
    public ConnectionFactory providerConnectionFactory(ActiveMQServer activeMQServer) {
        ActiveMQJMSConnectionFactory factory = new ActiveMQJMSConnectionFactory("vm://0");
        factory.setBlockOnAcknowledge(false);
        factory.setBlockOnDurableSend(false);
        factory.setBlockOnNonDurableSend(false);
        factory.setCacheDestinations(true);
        factory.setCompressLargeMessage(true);
        factory.setConfirmationWindowSize(1000000);
        factory.setThreadPoolMaxSize(100);

        PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
        pooledConnectionFactory.setConnectionFactory(factory);
        pooledConnectionFactory.setBlockIfSessionPoolIsFull(true);
        pooledConnectionFactory.setBlockIfSessionPoolIsFullTimeout(10000);
        pooledConnectionFactory.setReconnectOnException(true);
        pooledConnectionFactory.setCreateConnectionOnStartup(true);
        pooledConnectionFactory.setIdleTimeout(30000);
        pooledConnectionFactory.setExpiryTimeout(60000);
        pooledConnectionFactory.setMaxConnections(100);

        return pooledConnectionFactory;
    }

    @Bean
    public ConnectionFactory consumerConnectionFactory(ActiveMQServer activeMQServer) {
        ActiveMQJMSConnectionFactory factory = new ActiveMQJMSConnectionFactory("vm://0");
        factory.setBlockOnAcknowledge(false);
        factory.setBlockOnDurableSend(false);
        factory.setBlockOnNonDurableSend(false);
        factory.setCacheDestinations(true);
        factory.setCompressLargeMessage(true);
        factory.setConfirmationWindowSize(1000000);
        factory.setThreadPoolMaxSize(100);

        PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
        pooledConnectionFactory.setConnectionFactory(factory);
        pooledConnectionFactory.setBlockIfSessionPoolIsFull(true);
        pooledConnectionFactory.setBlockIfSessionPoolIsFullTimeout(10000);
        pooledConnectionFactory.setCreateConnectionOnStartup(true);
        pooledConnectionFactory.setIdleTimeout(30000);
        pooledConnectionFactory.setMaxConnections(100);
        pooledConnectionFactory.setReconnectOnException(true);
        pooledConnectionFactory.setExpiryTimeout(60000);
        return pooledConnectionFactory;
    }


    @Bean
    public JmsTemplate jmsTemplate(ConnectionFactory providerConnectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(providerConnectionFactory);
        jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
        jmsTemplate.setMessageIdEnabled(false);
        jmsTemplate.setExplicitQosEnabled(true);
        jmsTemplate.setPubSubNoLocal(false);
        jmsTemplate.setSessionTransacted(false);
        return jmsTemplate;
    }

    @Bean
    public JmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory consumerConnectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConcurrency("30-30");
        factory.setConnectionFactory(consumerConnectionFactory);
        factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
        factory.setSessionAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
        return factory;
    }
}
connection과 executor 설정은 해당 서버의 사용 용도에 맞게 따로 설정해주도록 합니다.