如何将Spring Boot JMS从ActiveMQ迁移到Oracle Advanced Queuing

时间:2017-04-17 19:46:11

标签: java oracle spring-boot spring-jms advanced-queuing

我正在研究Spring Boot和JMS示例,是的,我在这个

上相当新

由于我们使用Oracle,我想迁移Spring Boot&从ActiveMQ到Oracle Advanced Queuing的JMS示例。但是我真的很少发现这方面的信息。

据我所知,我需要为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 个答案:

答案 0 :(得分:3)

下面的配置将解决您的问题。

1 - 创建配置。对于这个答案,我已将所有配置文件压缩到应用程序文件中。你可以将它们放在单独的类中,从而分散关注点。

@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 jar分别添加到您的lib路径中,如this post所示。

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。我不会把它们放在这里。

@Testing,这就像魅力一样; - )

答案 1 :(得分:1)

我认为您不需要更改myFactory方法,而是需要创建连接到oracle队列的connectionFactory。我有类似的配置,在开发中我使用artemis来运行我的JUNIT而在prod中我使用了oracle队列。下面是我为创建connectionFactory定义的类。

paste0(tmpNames, tmpValues)

application.properties。

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获得了jar并从jar创建了maven依赖并推送到我的本地repo并将jar添加为依赖。

<weblogic_home>\wlserver\server\lib