Как перенести Spring Boot JMS из ActiveMQ в Oracle Advanced Queueing

Я изучаю пример Spring Boot и JMS, и да, я довольно новичок в этом

поскольку мы работаем с Oracle, я хотел бы перенести пример Spring Boot & JMS из ActiveMQ в Oracle Advanced Queueing. Однако я действительно нахожу очень мало информации об этом.

насколько я вижу, мне нужно заменить код ниже для версии Oracle, но мне не удалось узнать, как это сделать.

@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                                                DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all boot's default to this factory, including the message converter
    configurer.configure(factory, connectionFactory);
    // You could still override some of Boot's default if necessary.
    return factory;

}

исходный код можно найти по адресу Github

помощь была бы очень признательна!

2 ответов


конфигурация ниже решит ваши вопросы.

1-Создайте конфигурацию. Для этого ответа я поместил все файлы конфигурации compact в файл приложения. Вы можете поместить их в отдельные классы, тем самым разделяя проблемы.

@SpringBootApplication
@EnableJms
public class Application {
    private static Random rand = new Random();

    @Bean
    DataSource dataSource() throws SQLException {
        OracleDataSource dataSource = new OracleDataSource();
        dataSource.setUser("yourusername");
        dataSource.setPassword("yourpassword");
        dataSource.setURL("jdbc:oracle:thin:@yourserver:1521:xe");
        dataSource.setImplicitCachingEnabled(true);
        dataSource.setFastConnectionFailoverEnabled(true);
        return dataSource;
    }    

    @Bean
    public QueueConnectionFactory connectionFactory() throws Exception {
        return AQjmsFactory.getQueueConnectionFactory(dataSource());
    }

    @Bean
    public JmsTemplate jmsTemplate() throws Exception {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(connectionFactory());
        jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
        return jmsTemplate;
    }

    @Bean
    public JmsListenerContainerFactory<?> myJMSListenerFactory(QueueConnectionFactory connectionFactory,                                                      DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        //  factory.setConcurrency("15-20");
        factory.setMessageConverter(jacksonJmsMessageConverter());
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    @Bean
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
        for (int i = 0; i < 10; i++) {
            int waitSecs = rand.nextInt(3);
            jmsTemplate.convertAndSend("YourQueueName", new Email("info@example.com", "Hello " + i, waitSecs));
        }
    }
}

2-Сделайте свой слушатель JMS

@Component
public class Receiver {
    @JmsListener(destination = "YourQueueName", containerFactory = "myJMSListenerFactory")
    public void receiveEmail(Email email) {
        System.out.println("Received <" + email + ">");
    }
}

3-Maven и Oracle

вы можете добавить банки oracle6 или oracle7 отдельно к пути lib, как показано в этот пост.

остальная часть файла Mavan довольно стандартная.

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

4 - бизнес-объекты. Такие объекты, как электронная почта, являются вашим бизнес-доменом POJO. Я не положу их сюда.

@тестирования, это работает как шарм ;-)


Я не думаю, что вам нужно изменить метод myFactory как таковой, вместо этого вам нужно создать connectionFactory, который подключается к очереди oracle. У меня была аналогичная конфигурация, в dev я использовал artemis для запуска моего JUNIT, а в prod я использовал очередь oracle. Ниже приведен класс, который я определил для создания connectionFactory.

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.naming.Context;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.jndi.JndiTemplate;


/**
 * @author Karthik Prasad
 * @since 1.0.0.0
 *        <p>
 *        Configuration file for weblogic JMS connection
 */
@Configuration
@EnableJms
@ConfigurationProperties(prefix = "spring.wls.jms")
@ConditionalOnProperty(prefix = "spring.wls.jms", name = "url")
public class WLSJmsConfiguration {

    /**
     * SJ4J Log instance
     */
    private static final Logger LOG = LoggerFactory.getLogger(WLSJmsConfiguration.class);

    /**
     * provider url
     */
    private String url;
    /**
     * username of weblogic server using which JNDI connection will be
     * established
     */
    private String username;
    /**
     * password of weblogic server using which JNDI connection will be
     * established
     */
    private String password;
    /**
     * JMS Connection factory name configured in weblogic server
     */
    private String connectionFactoryName;

    /**
     * Name of destination queue
     */
    private String targetQueue;

    /**
     * The Response Queue
     */
    private String replyQueue;


    /**
     * URL to access weblogic Connectionfactory, property is set from properties
     * file
     * 
     * @see ConfigurationProperties
     * @param password
     *            weblogic url to JNDI
     */
    public void setUrl(final String url) {
        this.url = url;
    }

    /**
     * username to access weblogic queue, property is set from properties file
     * 
     * @see ConfigurationProperties
     * @param username
     *            weblogic username to access queue
     */
    public void setUsername(final String username) {
        this.username = username;
    }

    /**
     * Password to access weblogic queue, property is set from properties file
     * 
     * @see ConfigurationProperties
     * @param password
     *            weblogic password to access queue
     */
    public void setPassword(final String password) {
        this.password = password;
    }

    /**
     * Setter of connection factory name, property is set from properties file
     * 
     * @see ConfigurationProperties
     * @param connectionFactoryName
     *            ConnectionFactory from properties file
     */
    public void setConnectionFactoryName(final String connectionFactoryName) {
        this.connectionFactoryName = connectionFactoryName;
    }

    /**
     * Setter for {@link #targetQueue}
     * 
     * @param targetQueue
     *            the targetQueue to set
     */
    public void setTargetQueue(final String targetQueue) {
        this.targetQueue = targetQueue;
    }

    /**
     * @param replyQueue
     *            the replyQueue to set
     */
    public void setReplyQueue(final String replyQueue) {
        this.replyQueue = replyQueue;
    }


    /**
     * Get JNDI properties from properties file
     * 
     * @return list of Weblogic jndi properties
     */
    private Properties getJNDiProperties() {

        final Properties jndiProps = new Properties();
        LOG.debug("Initializing JndiTemplate");
        LOG.debug("Url is {}", url);
        jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        jndiProps.setProperty(Context.PROVIDER_URL, url);
        if (username != null && !username.isEmpty()) {
            jndiProps.setProperty(Context.SECURITY_PRINCIPAL, username);
        }
        if (password != null && !password.isEmpty()) {
            jndiProps.setProperty(Context.SECURITY_CREDENTIALS, password);
        }
        return jndiProps;

    }

    /**
     * Create JndiTemplate for target weblogic server from provided JNDI
     * properties
     * 
     * @return Bean of Jndi Template
     */
    @Bean
    public JndiTemplate jndiTemplate() {
        final JndiTemplate jndiTemplate = new JndiTemplate();
        jndiTemplate.setEnvironment(getJNDiProperties());
        return jndiTemplate;
    }

    /**
     * Creates instance of Jndi Object Factory bean from Jndi Template
     * 
     * @param jndiTemplate
     *            Jndi Template for weblogic server
     * @return Bean of JndiObject Factory
     */
    @Bean(name = "jmsJndiConnectionFactory")
    public JndiObjectFactoryBean jndiObjectFactoryBean(final JndiTemplate jndiTemplate) {

        final JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
        LOG.debug("Creating Weblogic JMS connection factory");
        jndiObjectFactoryBean.setJndiTemplate(jndiTemplate);
        // connectionFactory name.
        LOG.debug("ConnectoinFactory Name is {}", connectionFactoryName);
        jndiObjectFactoryBean.setJndiName(connectionFactoryName);
        return jndiObjectFactoryBean;

    }

    /**
     * Create Jms Connection factory from Jndi Objectfactory
     * 
     * @param jndiObjectFactoryBean
     *            Jndi Object factory bean
     * @return Returns Jms Connection factory Bean
     */
    @Bean(name = "jmsWlsConnectionFactory")
    public ConnectionFactory jmsConnectionFactory(final JndiObjectFactoryBean jndiObjectFactoryBean) {
        final ConnectionFactory connectionFactory = (ConnectionFactory) jndiObjectFactoryBean.getObject();
        LOG.debug("ConnectoinFactory is null? {}", connectionFactory == null);
        return connectionFactory;
    }

    /**
     * Wrap Weblogic Connection Factory around caching factory
     * 
     * @return
     */
    @Bean(name = "jmsConnectionFactory")
    @Primary
    public ConnectionFactory connectionFactoryProxy() {
        final CachingConnectionFactory jmsConnectionFactory = new CachingConnectionFactory(
                (ConnectionFactory) appContext.getBean("jmsWlsConnectionFactory"));
        jmsConnectionFactory.setCacheProducers(true);
        jmsConnectionFactory.setSessionCacheSize(20);
        return jmsConnectionFactory;
    }

    /**
     * The instance of Target Queue retrieved from JNDI, this bean is created in
     * dev profile, where one want to run the project in standalone mode but
     * want to connect to Weblogic Server
     * 
     * @return Bean of target queue instance
     */
    @Bean
    public Destination jmsQueueName() {

        final JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiTemplate(jndiTemplate());
        jndiObjectFactoryBean.setJndiName(targetQueue); // queue name
        return (Destination) jndiObjectFactoryBean.getObject();
    }

    /**
     * Create DestinationResolver to resolve QueueName
     * 
     * @return Instance of JNDI Destination Resolver
     */
    private DestinationResolver destinationResolver() {
        final JMSDestinationResolver destinationResolver = new JMSDestinationResolver();
        final JndiHelper jndiHelper = new JndiHelper(getJNDiProperties());
        destinationResolver.setJndiTemplate(jndiHelper);
        return destinationResolver;
    }

}

приложение.свойства.

spring.wls.jms.url=t3://server01:8001,server02:8003
spring.wls.jms.username=weblogic
spring.wls.jms.password=password
spring.wls.jms.connectionFactoryName=connectionFactory Name
spring.wls.jms.targetQueue=queue_name
spring.wls.jms.replyQueue=queue_name

и вам нужно добавить wlthint3client в вашем classpath. Я получил банку от <weblogic_home>\wlserver\server\lib и создал maven зависимость от jar и толкнул в мое локальное РЕПО и добавил jar как зависимость.

    <dependency>
        <groupId>com.oracle.weblogic</groupId>
        <artifactId>wlthint3client</artifactId>
        <version>12.2.1</version>
        <scope>provided</scope> <!-- comment out this if you are deploying on tomcat or running the application standalone -->
    </dependency>