我已经学会了如何用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并实现AQ功能。
现在,我正在尝试创建Java配置的bean,以便使用JmsTemplate
。
@Resource
private JmsTemplate jmsTemplate;
@Test
public void testJmsTemplate() {
String xmlval = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<product id=\"10\">\n" +
" <description>Foo</description>\n" +
" <price>2.05</price>\n" +
"</product>";
jmsTemplate.convertAndSend(aqSchema + ".jms_ws_incoming_queue", xmlval);
}
型
(yes,队列已存在;-))
使用以下配置类:
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.<init>(AQjmsDBConnMgr.java:399)
at oracle.jms.AQjmsConnection.<init>(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.<init>(AQjmsGeneralDBConnection.java:67)
at oracle.jms.AQjmsDBConnMgr.getConnection(AQjmsDBConnMgr.java:566)
... 41 more
型
我相信Cast异常的发生是因为它是一个ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@40016ce1]]
。但我不知道如何修复这个问题。
5条答案
按热度按时间toe950271#
更改
jdbc
库,在我的情况下,这修复了它(如果不这样做,请尝试使用其他版本):字符串
balp4ylt2#
我们在尝试从Sping Boot 访问Oracle AQ时遇到了相同的异常。研究表明,此异常是由于数据库连接池库不允许访问Oracle AQ库所需的底层连接而引发的。(dbcp和tomcat连接池库都引发了异常,不相同但相似)
当我们从依赖项中删除数据库连接池库时,这个异常就消失了,这会导致整个应用程序没有数据库连接池的不良状态。
我们注意到,如果我们使用以下方法,则不会抛出
AQjmsFactory.getQueueConnectionFactory(url, info);
异常也许解决方案中也缺少连接池,但这仅限于从AQ读取的组件。应用程序中的其他组件将具有连接池的好处。
下面是Bean定义的java配置:
字符串
我不知道这是否一个好的解决办法,但这肯定是一个方法,以消除问题中讨论的例外情况。
n1bvdmb63#
嗨,我也花了相当长的时间来使连接工作,但最后它做到了,这是如何:
首先,确保Oracle AQ队列表的有效负载未设置为RAW,而最好设置为Text:RAW.AQ$_JMS_TEXT_MESSAGE
接下来使用类似于下面的OracleAQConfiguration:
字符串
接下来使用类似于下面的JMSConfiguration。在这里,我读取和写入相同的队列,这在真实的应用程序集成场景中是不可能的。但是可以用于测试
型
最后,对于处理传入的JMS消息,使用类似于:
型
n1bvdmb64#
问题是AQ代码需要OracleConnection,但在池化时连接被 Package ,因此失败
ljsrvy3e5#
字符串
//使用Spring JMS模板向Oracle AQ JMS队列发送消息的代码
型