2017-04-17 72 views
7

我学习的春天引导和JMS例子,是的,我在这头如何春季启动JMS迁移从ActiveMQ的到Oracle高级队列

由于我们与甲骨文合作,而新的,我想迁移从ActiveMQ到Oracle高级队列的Spring Boot & 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

帮助找到将不胜感激!

+0

恕我直言,这是故意的。如果您的代码在WebLogic(也是Oracle产品)上运行,那么安装非常简单(请参阅http://danielveselka.blogspot.cz/2009/07/mdb-3-0-on-weblogic-103-using-oracle -aq.html)。恐怕其他应用程序服务器不提供JMS到AQ连接器(资源适配器)。 – ibre5041

+0

不,我不想连接到WebLogic,而是直接连接到Oracle高级队列(AQ)。 在我没有使用Spring Boot的程序中,我使用: '\t \t \t qconFactory = AQjmsFactory.getQueueConnectionFactory(hostName,serviceName,port,“thin”); \t \t \t qcon = qconFactory.createQueueConnection(userName,password); \t \t \t qsession = qcon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); \t \t \t queueTable =((AQjmsSession)qsession).getQueueTable(userName,queueTableName); \t \t \t queue =((AQjmsSession)qsession).getQueue(userName,queueName); ' – dhmc

+0

什么是尝试解释是。 Oracle AQ可以充当标准的Java EE JMS提供程序。这可能会让你从ActiveMQ过渡更容易。 (实际上在源代码中没有改变)。但是这可能只在某些情况下才起作用。 – ibre5041

回答

1

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

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("[email protected]", "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和甲骨文

可以seperately添加ORACLE6或Oracle7的罐子到库的路径,如图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

我不认为你需要改变myFactory方法,而是需要创建connectionFactory,它连接到oracle队列。我有类似的配置,在开发中我使用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; 
    } 

} 

application.properties。

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添加到您的类路径中。我从<weblogic_home>\wlserver\server\lib获得了jar,并从jar中创建了maven依赖项,并推送到我的本地回购库中,并添加了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> 
+0

感谢您的回答。非常适合每个使用WebLogic的人。 但是,如何在不需要WEBLOGIC的情况下连接到Oracle Advanced Queuing(AQ)。 那么Spring入门JMS示例中的Spring AQ等效的ActiveMQ代码是什么,请参见[Spring Boot入门JMS] [1] 或者Github上的[spring-boot-sample-activemq示例] [ 2] [1]:https://spring.io/guides/gs/messaging-jms/ [2]:https://github.com/spring-projects/spring-boot/tree/master/spring -boot采样/弹簧引导样品的ActiveMQ – dhmc