eisentor
eisentor

Reputation: 68

Java Oracle UCP Datapool is not working in Junit Test, but in other situations

The Junit Integrationtest fails during initialization of the OracleConnection Pool. My main issue is if i'am starting the same in my production environment or out of a simple main method it works. All are using the same connection properties.

The execution with junit always fails at this code section:

this.universalConnectionPool.start();

Stacktrace/Error message:

Caused by: com.xelog.nx.wms.hardware.hrl.HRLDriverException: java.lang.AssertionError: pool start procedure finished with wrong life cycle state, lifecycle=Starting
    at com.xelog.nx.wms.hardware.hrl.OracleConnectionProvider.<init>(OracleConnectionProvider.java:128)
    ... 72 more
Caused by: java.lang.AssertionError: pool start procedure finished with wrong life cycle state, lifecycle=Starting
    at oracle.ucp.common.UniversalConnectionPoolBase.start(UniversalConnectionPoolBase.java:903)
    at oracle.ucp.jdbc.oracle.OracleJDBCConnectionPool.start(OracleJDBCConnectionPool.java:143)
    at oracle.ucp.jdbc.oracle.OracleReplayableConnectionConnectionPool.start(OracleReplayableConnectionConnectionPool.java:102)
    at oracle.ucp.UniversalConnectionPool.start(UniversalConnectionPool.java:224)
    ... 74 more

I simply want to start a connection pool in any way i've starting my application SpringBoot, simple main method or a Junit test. The first and the second way are working, the junit fails.

I've tried many ways of creating the connectionpool, directly with the UCPManager or with PoolDataSource, everythings ends in the same mess with the junit test.

This is the shared code to start the connection pool:

package com.test;

import oracle.ucp.UniversalConnectionPool;
import oracle.ucp.UniversalConnectionPoolAdapter;
import oracle.ucp.UniversalConnectionPoolException;
import oracle.ucp.UniversalConnectionPoolLifeCycleState;
import oracle.ucp.admin.UniversalConnectionPoolManager;
import oracle.ucp.admin.UniversalConnectionPoolManagerImpl;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import oracle.ucp.jdbc.PoolDataSourceImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.URL;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.Random;

public class OracleConnectionProvider {
    
    private static final Logger LOG = LogManager.getLogger(OracleConnectionProvider.class);
    
    private static final long MAX_STARTUP_WAIT_MILLIS = 5000;//30000;
    
    private final String connectionFactory;
    private final String url;
    private final String user;
    private final String password;
    
    private final String connectionPoolName;
    private PoolDataSource pds;
    private UniversalConnectionPool universalConnectionPool;
    
    public OracleConnectionProvider(final String connectionFactory, final String url, final String user, final String password,
                                    final Map<String, String> propertyMap, final String poolName, final int minPoolSize, final int maxPoolSize) throws HRLDriverException {
        
        
        this.connectionFactory = connectionFactory;
        this.url = url;
        this.user = user;
        this.password = password;
        
        this.connectionPoolName = poolName;
        
        final long startOracleConnectionProvider = System.currentTimeMillis();
        try {
            final UniversalConnectionPoolManager ucpManager = UniversalConnectionPoolManagerImpl.getUniversalConnectionPoolManager();
            
            this.pds = PoolDataSourceFactory.getPoolDataSource();
            this.pds.setConnectionPoolName(this.connectionPoolName);
            this.pds.setConnectionFactoryClassName(this.connectionFactory);
            this.pds.setURL(this.url);
            this.pds.setUser(this.user);
            this.pds.setPassword(this.password);
            this.pds.setValidateConnectionOnBorrow(true);
            this.pds.setInitialPoolSize(minPoolSize);
            this.pds.setMinPoolSize(minPoolSize);
            this.pds.setMaxPoolSize(maxPoolSize);

            // Default is 30secs. Set the frequency in seconds to enforce the timeout
            // properties. Applies to inactiveConnectionTimeout(int secs),
            // AbandonedConnectionTimeout(secs)& TimeToLiveConnectionTimeout(int secs).
            // Range of valid values is 0 to Integer.MAX_VALUE. .
            this.pds.setTimeoutCheckInterval(5);
            
            // Default is 0. Set the maximum time, in seconds, that a
            // connection remains available in the connection pool.
            this.pds.setInactiveConnectionTimeout(10);
            
            if (propertyMap != null && !propertyMap.isEmpty()) {
                final Properties properties = this.pds.getConnectionProperties();
                properties.putAll(propertyMap);
                this.pds.setConnectionProperties(properties);
            } else {
                this.pds.setConnectionProperties(new Properties());
            }
             
            if (!(this.pds instanceof UniversalConnectionPoolAdapter)) {
                LOG.info("Not expected implementation {}, pool sanity check not possible", UniversalConnectionPoolAdapter.class);
            }
            
            final UniversalConnectionPoolAdapter connectionPoolAdapter = (UniversalConnectionPoolAdapter) this.pds;
            connectionPoolAdapter.createUniversalConnectionPool();
            
            this.universalConnectionPool = ucpManager.getConnectionPool(this.connectionPoolName);
            this.universalConnectionPool.start();

            LOG.info("Startup - Initial");
            UniversalConnectionPoolLifeCycleState loopLifeCycleState = UniversalConnectionPoolLifeCycleState.LIFE_CYCLE_STARTING;
            while ((System.currentTimeMillis() - startOracleConnectionProvider) < MAX_STARTUP_WAIT_MILLIS
                    && loopLifeCycleState != UniversalConnectionPoolLifeCycleState.LIFE_CYCLE_RUNNING) {
                LOG.info("Startup - Waited {}ms not ready {}", System.currentTimeMillis() - startOracleConnectionProvider, loopLifeCycleState);
                loopLifeCycleState = this.universalConnectionPool.getLifeCycleState();
                Thread.sleep(500);
            }
            
            final UniversalConnectionPoolLifeCycleState finalLifeCycleState = this.universalConnectionPool.getLifeCycleState();
            if (finalLifeCycleState != UniversalConnectionPoolLifeCycleState.LIFE_CYCLE_RUNNING) {
                LOG.warn("Startup - Wrong State {}, max wait time of {}ms exceeded.", finalLifeCycleState, MAX_STARTUP_WAIT_MILLIS);
            } else {
                LOG.info("Startup - Successfully started within {}ms", System.currentTimeMillis() - startOracleConnectionProvider);
            }
        } catch (final InterruptedException e) {
            LOG.error("Error while initializing the data source, thread was interrupted", e);
            Thread.currentThread().interrupt();
        } catch (final SQLException e) {
            LOG.error("Error while initializing the data source", e);
            throw new HRLDriverException(e);
        } catch (final UniversalConnectionPoolException e) {
            LOG.error("Error while initializing the universal connection pool manager.", e);
            throw new HRLDriverException(e);
        } catch (final Throwable e) {
            LOG.error("Error while initializing the driver.", e);
            throw new HRLDriverException(e);
        }
    }

    public Connection getConnection() throws SQLException {
        if(this.universalConnectionPool.getLifeCycleState() != UniversalConnectionPoolLifeCycleState.LIFE_CYCLE_RUNNING){
            throw new SQLException("Pool is not running, state is " + this.universalConnectionPool.getLifeCycleState());
        }
        return this.pds.getConnection();
    }
    
    public void destroy() throws SQLException {
        if (this.pds != null) {
            this.pds.setInitialPoolSize(0);
            this.pds.setMinPoolSize(0);
            this.pds.setMaxPoolSize(0);
            final UniversalConnectionPoolLifeCycleState lifeCycleState = this.universalConnectionPool.getLifeCycleState();
            try {
                if(lifeCycleState == UniversalConnectionPoolLifeCycleState.LIFE_CYCLE_STOPPED){
                    LOG.info("Connection pool is already in state {}", this.universalConnectionPool.getLifeCycleState());
                } else {
                    LOG.info("Connection pool try to purge with state {}", lifeCycleState);
                    this.universalConnectionPool.purge();
                    LOG.info("Connection pool '{}' successfully purged final state {}", this.connectionPoolName, this.universalConnectionPool.getLifeCycleState());
                }
            } catch (final UniversalConnectionPoolException e) {
                LOG.error("Connection pool {} purge failed with state {}",this.connectionPoolName, lifeCycleState, e);
            } catch (final Throwable e){
                LOG.error("Connection pool {} purge failed with unknown error with state {}", this.connectionPoolName, lifeCycleState, e);
            }
        }
    }
}

The oracle dependencies are used as follows: this is not working

dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>23.2.0.0</version>
</dependency>
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ucp</artifactId>
    <version>23.2.0.0</version>
</dependency>

this is working

dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8-production</artifactId>
    <version>23.2.0.0</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ucp</artifactId>
    <version>23.2.0.0</version>
</dependency>

Upvotes: 0

Views: 337

Answers (1)

Saurabh Verma
Saurabh Verma

Reputation: 300

Could you try disabling the assertions and see if that works? Also, please note that 23.2 is a developer release, so you should not use it in production.

Upvotes: 1

Related Questions