Интерфейсы UCP тонкого клиента Hibernate 5 + Spring + JDBC не видны загрузчику классов - PullRequest
0 голосов
/ 28 января 2019

Я обновил следующие библиотеки:

  • Spring 3.2.0 -> 4.3.22
  • Hibernate 4.1.1 -> 5.1.11

Следует отметить, что я также использую библиотеки тонких клиентов JDBC

  • OJDBC 7
  • ucp 12.1.0
  • ons 12.1.0

Я работаю над службой Axis2, которая заканчивается, развернута на сервере приложений WSO2.Частью инициализации является загрузка фабрики сеансов гибернации.Это определение выглядит следующим образом.

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name = "dataSource" ref = "dataSource"></property>
</bean>

Когда я иду для инициализации компонента, я делаю это через ClassPathXmlApplicationContext, указывающий на файл с моим определением фабрики сеанса гибернации.

final ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(new String[] {"repository/conf/pda/applicationContext_dataInventory.xml"}, false)
appCtx.setClassLoader(classLoader);
appCtx.refresh(); // <--- Causes error

КогдаЯ звоню appCtx.refresh(), я получаю исключение, заявляющее

Caused by: java.lang.IllegalArgumentException: interface oracle.ucp.jdbc.LabelableConnection is not visible from class loader
        at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:616)
        at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:592)
        at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:244)
        at java.lang.reflect.WeakCache.get(WeakCache.java:141)
        at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:455)
        at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:738)
        at oracle.ucp.jdbc.proxy.ConnectionProxyFactory.createConnectionProxy(ConnectionProxyFactory.java:79)
        at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:1046)
        at com.xxx.espds.cim.dataMgmt.hibernate.FailoverPoolDataSource.getConnection(FailoverPoolDataSource.java:519)
        at com.xxx.espds.cim.dataMgmt.hibernate.FailoverPoolDataSource.getConnection(FailoverPoolDataSource.java:497)
        at com.xxx.espds.cim.dataMgmt.hibernate.FailoverPoolDataSource.getConnection(FailoverPoolDataSource.java:492)
        at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
        at org.hibernate.internal.SessionFactoryImpl$3.obtainConnection(SessionFactoryImpl.java:677)
        at org.hibernate.hql.spi.id.IdTableHelper.executeIdTableCreationStatements(IdTableHelper.java:67)
        at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:125)
        at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:42)
        at org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl.prepare(AbstractMultiTableBulkIdStrategyImpl.java:88)
        at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:471)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:422)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:711)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:727)
        at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:511)
        at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:495)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627)

Если я вручную загружу класс перед вызовом обновления, вызвав appCtx.getClassLoader().loadClass("oracle.ucp.jdbc.LabelableConnection");, то эта конкретная ошибка исчезнет, ​​но я просто получуошибка на другом интерфейсе, не видимая для загрузчика классов.Я думаю, что это как-то связано с Spring / Hibernate, не использующим тот же classLoader, который я дал для ClassPathXmlApplicationContext.

Почему классы UCP не видны во время инициализации фабрики сеансов?

1 Ответ

0 голосов
/ 30 января 2019

Проблема была решена путем установки загрузчика классов для потоков в ClassLoader, используемый для ClassPathXmlApplicationContext.JDBC оракула в конечном итоге пытается загрузить некоторые свои собственные классы из зависимости UCP, используя Thread.currentThread().getContextClassLoader();.Код, иллюстрирующий исправление, подробно описан ниже

// Get current thread ClassLoader and reset it after we do the initial load. While we previously set the
// Spring ClassLoader, when we initialize the UCP ConnectionPool via the hibernate sessionFactory the jdbc
// thin client attempts to load classes using the currentThread().getContextClassLoader(). To get around this,
// we need to set the threads ClassLoader to the one that has information on the JDBC libraries, and since we
// always package up the libraries in each service, that would be the service.getClassLoader()
final ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"}, false);
appCtx.setClassLoader(classLoader);
ClassLoader threadLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
appCtx.refresh();
Thread.currentThread().setContextClassLoader(threadLoader);
...