2017-04-19 2 views
0

AQ (Streams?) 패키지가있는 Oracle 데이터베이스를 만드는 방법을 이미 알았습니다. 필자는 오라클에 대기열을 손으로 만들었습니다. (PL/SQL과 SQL 사용).스프링 부트에서 Oracle AQ 큐를 구현하는 방법은 무엇입니까?

그러나 Spring과의 적절한 연결을 설정하는 데 어려움을 겪고 있습니다. (oracle.AQ 자바 패키지를 사용)

다음 작품 : (https://docs.oracle.com/cd/B10501_01/appdev.920/a96587/apexampl.htm 기준)

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()); 

} 

이 나를 보여 내가 오라클에 연결하고 AQ 기능에 도달 할 수있다.

이제 JmsTemplate을 사용하기 위해 Java Configured beans를 만들려고합니다.

@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); 
} 

(예, 큐가 이미 존재 ;-)) 다음과 같은 구성 클래스와

:

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 

나는 캐스트 결과가 ProxyConnection[PooledConnection[[email protected]]]이기 때문에 발생한다고 생각합니다. 그러나 나는 이것을 고치는 법을 모른다.

답변

0

스프링 부트에서 Oracle AQ에 액세스하려고 시도했을 때와 동일한 예외가 발생했습니다. 연구 결과에 따르면 데이터베이스 연결 풀 라이브러리가 oracle AQ 라이브러리에 필요한 기본 연결에 대한 액세스를 허용하지 않기 때문에이 예외가 발생합니다 (dbcp 및 tomcat 연결 풀 라이브러리는 동일하지만 유사하지 않은 예외를 던졌습니다)

데이터베이스 연결 풀 라이브러리를 종속성에서 제거하여 전체 응용 프로그램에 대해 데이터베이스 연결 풀링을 필요로하지 않는 바람직하지 않은 상태가 될 때이 예외가 사라졌습니다.

우리는 발견이 우리가 예외가 AQjmsFactory.getQueueConnectionFactory(url, info);

는 아마도 연결 풀링은 또한 솔루션이 없습니다 슬로우되지 않는 다음과 같은 방법을 사용하지만, 그 AQ에서 읽는 구성 요소로 제한됩니다. 응용 프로그램의 다른 구성 요소가 여기에

연결 풀링의 장점이있을 것이다하는 것은 Bean 정의를위한 자바 설정입니다 :

@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; 
} 

나는 확실하지 않다 아직이 경우에 좋은 솔루션입니다. 그러나 이것은 질문에서 논의 된 예외를 제거하는 한 가지 방법입니다.

0

jdbc 도서관이 그것을 고정 내 경우에는 (그렇게하지 않으면, 다른 버전으로 시도) 변경 :

<dependency> 
    <groupId>com.oracle</groupId> 
    <artifactId>ojdbc7</artifactId> 
    <version>12.1.0.2.0</version> 
</dependency> 
관련 문제