I would like to have one transaction, one commit and one database connection 
for an Apache Camel route that only uses Oracle. In my current setup it appears 
that the Oracle AQ JMS transaction and the Oracle INSERT transaction are 
separate.

Why do I want it

    With separate transactions there is the possibility of duplicate row 
INSERTs.
    The current setup borrows two database connections from the pool. One for 
JMS and one for INSERT. Every route uses twice the number of database 
connections of which there are a limited supply.

How do I know

    When the routes are running under load I can kill -9 the camel process. The 
result is that the in-flight message rolls back, but the INSERTed row remains.

I have some apache camel routes that operate on the Oracle database. The route 
starts from an Oracle AQ, inserts some rows into a few database tables and 
finally sends the message to another Oracle AQ.

Example Route java code

from(getInputAQ())
.routeId("AQ_ROUTE")
.autoStartup(true)
.transacted("PROPAGATION_REQUIRED")
.process("OracleInsertProcessor")
.to(getOutputAQ())

Example INSERT java code

@Autowired
private JdbcTemplate jdbcTemplate;

public int save(List<T> list)
{
    int[] insertCountArray = getJdbcTemplate().batchUpdate(getInsertQuery(), 
new BatchPreparedStatementSetter()
    {
        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException
        {
            buildInsertParameters(ps, list.get(i));
        }

        @Override
        public int getBatchSize()
        {
            return list.size();
        }
    });
    return getTotalCount(insertCountArray);
}

Context file

<!-- oracle aq set up -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>
    
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" 
factory-method="getPoolDataSource">
    <property name="URL" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.pwd}')}" />
    <property name="connectionFactoryClassName" 
value="oracle.jdbc.pool.OracleDataSource" />
    <property name="connectionPoolName" value="ORACLE_POOL" />
    <property name="minPoolSize" value="${minPoolSize}" />
    <property name="maxPoolSize" value="${maxPoolSize}" />
    <property name="initialPoolSize" value="${initialPoolSize}" />
    <property name="queryTimeout" value="${queryTimeout}" />
    <property name="inactiveConnectionTimeout" 
value="${inactiveConnectionTimeout}" />
    <property name="validateConnectionOnBorrow" value="true" />
    <property name="secondsToTrustIdleConnection" 
value="${secondsToTrustIdleConnection}" />
    <property name="timeToLiveConnectionTimeout" 
value="${timeToLiveConnectionTimeout}" />
    <property name="maxStatements" value="10" />
</bean>
    
<bean id="dbTransactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <property name="defaultTimeout" value = "60"/>
</bean>
    
<bean id="PROPAGATION_REQUIRED" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="dbTransactionManager" />
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" />
</bean>
    
<bean id="PROPAGATION_REQUIRES_NEW" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="dbTransactionManager" />
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" />
</bean>
  
<bean id="PROPAGATION_SUPPORTS" 
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="dbTransactionManager" />
    <property name="propagationBehaviorName" value="PROPAGATION_SUPPORTS" />
</bean>

<bean id="aqJmsConnectionFactory" class="oracle.jms.AQjmsConnectionFactory">
    <property name="datasource" ref="dataSource"/>
</bean>

<bean id="aqjms" class="org.apache.camel.component.jms.JmsComponent">
    <property name="connectionFactory" ref="aqJmsConnectionFactory" />
    <property name="transacted" value="true" />
    <property name="transactionManager" ref="dbTransactionManager" />
</bean>

When thinking about solutions for this problem, it seems that reusing the 
database connection used by the Apache Camel JMS component could be a solution. 
I suppose there is a problem somewhere in my setup.



--
I have also posted this question to stackoverflow. 
https://stackoverflow.com/questions/67493188/apache-camel-single-transaction-with-oracle-aq-and-row-inserts
--
Alex Mattern

*************************** IMPORTANT NOTE*****************************
The opinions expressed in this message and/or any attachments are those of the 
author and not necessarily those of Brown Brothers Harriman & Co., its 
subsidiaries and affiliates ("BBH"). There is no guarantee that this message is 
either private or confidential, and it may have been altered by unauthorized 
sources without your or our knowledge. Nothing in the message is capable or 
intended to create any legally binding obligations on either party and it is 
not intended to provide legal advice. BBH accepts no responsibility for loss or 
damage from its use, including damage from virus.
******************************************************************************

Reply via email to