如何在Spring Boot中实现Oracle AQ队列?

我已经了解了如何使用AQ(Streams?)包创建Oracle数据库。 我还在Oracle中创建了一些队列(手动)。 (使用PL / SQL和SQL)。

但是,我很难从Spring建立正确的连接。

以下工作(使用oracle.AQ java包):

 private final String aqUrl = "jdbc:oracle:thin:@localhost:1521:orcl"; private final String aqUser = "queue_mut"; private final String aqPassword = "******"; private final String aqSchema = "queue_mut"; private final String aqTable = "aq_table1"; private final String aqQueue = "aq_queue1"; @Test public void testManualAQ() throws ClassNotFoundException, SQLException, AQException { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection connection = DriverManager.getConnection(aqUrl, aqUser, aqPassword); connection.setAutoCommit(false); Class.forName("oracle.AQ.AQOracleDriver"); AQSession aqSession = AQDriverManager.createAQSession(connection); AQQueueTable q_table = aqSession.createQueueTable(aqSchema, aqTable, new AQQueueTableProperty("RAW")); aqSession.createQueue(q_table, aqQueue, new AQQueueProperty()); } 

(基于https://docs.oracle.com/cd/B10501_01/appdev.920/a96587/apexampl.htm )

这告诉我,我可以连接到Oracle并实现AQfunction。

现在,我正在尝试创建Java Configured bean以便使用JmsTemplate

 @Resource private JmsTemplate jmsTemplate; @Test public void testJmsTemplate() { String xmlval = "\n" + "\n" + " Foo\n" + " 2.05\n" + ""; jmsTemplate.convertAndSend(aqSchema + ".jms_ws_incoming_queue", xmlval); } 

(是的,队列已经存在;-))

使用以下配置类:

 import oracle.jms.AQjmsFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jms.core.JmsTemplate; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.sql.DataSource; @Configuration public class OracleAQConfiguration { @Bean public DataSourceTransactionManager transactionManager(DataSource dataSource) { DataSourceTransactionManager manager = new DataSourceTransactionManager(); manager.setDataSource(dataSource); return manager; } @Bean public ConnectionFactory connectionFactory(DataSource dataSource) throws JMSException { return AQjmsFactory.getQueueConnectionFactory(dataSource); } @Bean public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { JmsTemplate jmsTemplate = new JmsTemplate(); jmsTemplate.setSessionTransacted(true); jmsTemplate.setConnectionFactory(connectionFactory); return jmsTemplate; } } 

并使用属性yml:

 spring: datasource: url: jdbc:oracle:thin:@localhost:1521:orcl username: queue_mut password: ****** driverClassName: oracle.jdbc.driver.OracleDriver 

但是有了这个,我得到了一些我无法理解的错误:

 2017-04-19 12:11:17,151 INFO my.project.QueueTest: Started QueueTest in 5.305 seconds (JVM running for 6.588) org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is oracle.jms.AQjmsException: Error creating the db_connection; nested exception is java.lang.ClassCastException: com.sun.proxy.$Proxy102 cannot be cast to oracle.jdbc.internal.OracleConnection at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316) at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:487) at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:570) at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:658) at my.project.QueueTest.testJmsTemplate(QueueTest.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused by: oracle.jms.AQjmsException: Error creating the db_connection at oracle.jms.AQjmsDBConnMgr.getConnection(AQjmsDBConnMgr.java:625) at oracle.jms.AQjmsDBConnMgr.(AQjmsDBConnMgr.java:399) at oracle.jms.AQjmsConnection.(AQjmsConnection.java:249) at oracle.jms.AQjmsConnectionFactory.createConnection(AQjmsConnectionFactory.java:513) at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:180) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:474) ... 36 more Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy102 cannot be cast to oracle.jdbc.internal.OracleConnection at oracle.jms.AQjmsGeneralDBConnection.getProviderKey(AQjmsGeneralDBConnection.java:98) at oracle.jms.AQjmsGeneralDBConnection.(AQjmsGeneralDBConnection.java:67) at oracle.jms.AQjmsDBConnMgr.getConnection(AQjmsDBConnMgr.java:566) ... 41 more 

我相信Castexception的发生是因为它是ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@40016ce1]] 。 但我不知道如何解决这个问题。

尝试从Spring启动访问Oracle AQ时遇到了相同的exception。 研究表明,抛出此exception是因为数据库连接池库不允许访问oracle AQ库所需的底层连接。(dbcp和tomcat连接池库都抛出exception,不是相同但相似)

当我们从依赖项中删除数据库连接池库时,这个exception就消失了,这导致了整个应用程序没有数据库连接池的不良状态。

我们注意到,如果我们使用以下方法,则不会抛出exceptionAQjmsFactory.getQueueConnectionFactory(url, info);

解决方案也许缺少连接池,但这仅限于从AQ读取的组件。 应用程序中的其他组件将具有连接池的优势

这是Bean定义的java配置:

 @Bean public QueueConnectionFactory connectionFactory() throws Exception { OracleServiceInfo serviceInfo = (OracleServiceInfo) this.cloud().getServiceInfo(NAME_PRIMARY_DS); Properties info = new Properties(); String url = serviceInfo.getJdbcUrl(); info.put("driver-name", "oracle.jdbc.OracleDriver"); info.put("user", serviceInfo.getUserName()); info.put("password", serviceInfo.getPassword()); return oracle.jms.AQjmsFactory.getQueueConnectionFactory(url, info); } @Bean public JmsTemplate jmsTemplate() throws Exception { JmsTemplate jmsTemplate = new JmsTemplate(); jmsTemplate.setConnectionFactory(connectionFactory()); return jmsTemplate; } 

我不确定这是否是一个好的解决方案。 但这绝对是摆脱问题中讨论的exception的一种方法。

更改jdbc库,在我的情况下修复它(如果没有,请尝试使用其他一些版本):

  com.oracle ojdbc7 12.1.0.2.0  
Interesting Posts