为什么在 Apache Storm 中通过 Spring 配置时 Flexy-Pool 会导致 NoSuchElementException
Why does Flexy-Pool cause a NoSuchElementException when configured via Spring in Apache Storm
我有一个基于 Apache Storm (1.1.1
) 的应用程序,它使用 Spring (5.0.3
) 配置和注入基于 Hibernate 的 (5.2.12
) 数据库服务,连接到 PostgreSQL 数据库。
在 Hibernate 和数据库之间,我配置了 flexy-pool (2.0.0
) on top of HikariCP (2.7.6
) 作为数据源(见图 A)。该应用程序在某些 Ubuntu 具有最新 OpenJDK 8 版本的 16.04 LTS 服务器实例上启动。
在启动我的 Storm
拓扑后,我遇到了与 flexy-pool
相关的令人伤心的运行时异常。但是,这 不是 确定性的。有时它会起作用,有时会抛出下面的异常。如果我不在我的应用程序中使用 flexy-pool
(参见图 B),一切都会按预期进行。
Caused by:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.vladmihalcea.flexypool.config.Configuration]: Factory method 'build' threw exception; nested exception is java.util.NoSuchElementException at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579) ... 42 more
Caused by:
java.util.NoSuchElementException at
sun.misc.URLClassPath.nextElement(URLClassPath.java:282) at
sun.misc.URLClassPath.nextElement(URLClassPath.java:256) at
java.net.URLClassLoader.run(URLClassLoader.java:603) at
java.net.URLClassLoader.run(URLClassLoader.java:599) at
java.security.AccessController.doPrivileged(Native Method) at
java.net.URLClassLoader.next(URLClassLoader.java:598) at
java.net.URLClassLoader.hasMoreElements(URLClassLoader.java:623) at
sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45) at
sun.misc.CompoundEnumeration.nextElement(CompoundEnumeration.java:58) at
java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357) at
java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393) at
java.util.ServiceLoader.hasNext(ServiceLoader.java:474) at
com.vladmihalcea.flexypool.metric.MetricsFactoryResolver.resolve(MetricsFactoryResolver.java:27) at
com.vladmihalcea.flexypool.config.Configuration$Builder.build(Configuration.java:165) 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.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
图B中使用的Spring配置就是这个(基于官方sample):
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP"/>
<property name="connectionTestQuery" value="SELECT 1"/>
<property name="dataSourceClassName" value="${gmetric.dataSourceClassName}"/>
<property name="dataSourceProperties">
<props>
<prop key="url">${shc.gmetric.url}</prop>
<prop key="user">${shc.gmetric.username}</prop>
<prop key="password">${shc.gmetric.pw}</prop>
</props>
</property>
</bean>
<bean id="poolingDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig"/>
</bean>
<bean id="configurationBuilder" class="com.vladmihalcea.flexypool.config.Configuration$Builder">
<constructor-arg value="uniqueId"/>
<constructor-arg ref="poolingDataSource"/>
<constructor-arg value="#{ T(com.vladmihalcea.flexypool.adaptor.HikariCPPoolAdapter).FACTORY }"/>
</bean>
<bean id="configuration" factory-bean="configurationBuilder" factory-method="build"/>
<bean id="flexyPoolDataSource" class="com.vladmihalcea.flexypool.FlexyPoolDataSource" init-method="start" destroy-method="stop">
<constructor-arg ref="configuration"/>
<constructor-arg>
<array>
<bean class="com.vladmihalcea.flexypool.strategy.IncrementPoolOnTimeoutConnectionAcquiringStrategy.Factory">
<constructor-arg value="5"/>
</bean>
<bean class="com.vladmihalcea.flexypool.strategy.RetryConnectionAcquiringStrategy.Factory">
<constructor-arg value="2"/>
</bean>
</array>
</constructor-arg>
</bean>
<bean id="entityManagerFactoryGMetrics"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="flexyPoolDataSource"/>
<property name="persistenceUnitName" value="${gmetric.context.name}"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--<property name="generateDdl" value="true" />-->
<property name="databasePlatform" value="${hibernate.dialect}"/>
<property name="showSql" value="${hibernate.showSQL}"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.driver_class">${gmetric.driverClassName}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.showSQL}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
我的问题是:
- 我的
flexy-pool
基于 Spring 的(默认)配置是否正确?
- 是否有解决方案来防止与
flexy-pool
相关的运行时异常?
- 这是什么原因
NoSuchElementException
?
我发现 Dropwizard Metrics 4(flexy-pool
需要)在我的阴影 jar 中丢失,因此发生了这个有线运行时异常:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
根据 author,这与 flexy-pool
检测相关 Dropwizard Metrics 处理程序的方式有关(因为它支持不能互换使用的 DM3 和 DM4)。
我有一个基于 Apache Storm (1.1.1
) 的应用程序,它使用 Spring (5.0.3
) 配置和注入基于 Hibernate 的 (5.2.12
) 数据库服务,连接到 PostgreSQL 数据库。
在 Hibernate 和数据库之间,我配置了 flexy-pool (2.0.0
) on top of HikariCP (2.7.6
) 作为数据源(见图 A)。该应用程序在某些 Ubuntu 具有最新 OpenJDK 8 版本的 16.04 LTS 服务器实例上启动。
在启动我的 Storm
拓扑后,我遇到了与 flexy-pool
相关的令人伤心的运行时异常。但是,这 不是 确定性的。有时它会起作用,有时会抛出下面的异常。如果我不在我的应用程序中使用 flexy-pool
(参见图 B),一切都会按预期进行。
Caused by:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.vladmihalcea.flexypool.config.Configuration]: Factory method 'build' threw exception; nested exception is java.util.NoSuchElementException at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579) ... 42 more
Caused by:
java.util.NoSuchElementException at
sun.misc.URLClassPath.nextElement(URLClassPath.java:282) at
sun.misc.URLClassPath.nextElement(URLClassPath.java:256) at
java.net.URLClassLoader.run(URLClassLoader.java:603) at
java.net.URLClassLoader.run(URLClassLoader.java:599) at
java.security.AccessController.doPrivileged(Native Method) at
java.net.URLClassLoader.next(URLClassLoader.java:598) at
java.net.URLClassLoader.hasMoreElements(URLClassLoader.java:623) at
sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45) at
sun.misc.CompoundEnumeration.nextElement(CompoundEnumeration.java:58) at
java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357) at
java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393) at
java.util.ServiceLoader.hasNext(ServiceLoader.java:474) at
com.vladmihalcea.flexypool.metric.MetricsFactoryResolver.resolve(MetricsFactoryResolver.java:27) at
com.vladmihalcea.flexypool.config.Configuration$Builder.build(Configuration.java:165) 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.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
图B中使用的Spring配置就是这个(基于官方sample):
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP"/>
<property name="connectionTestQuery" value="SELECT 1"/>
<property name="dataSourceClassName" value="${gmetric.dataSourceClassName}"/>
<property name="dataSourceProperties">
<props>
<prop key="url">${shc.gmetric.url}</prop>
<prop key="user">${shc.gmetric.username}</prop>
<prop key="password">${shc.gmetric.pw}</prop>
</props>
</property>
</bean>
<bean id="poolingDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig"/>
</bean>
<bean id="configurationBuilder" class="com.vladmihalcea.flexypool.config.Configuration$Builder">
<constructor-arg value="uniqueId"/>
<constructor-arg ref="poolingDataSource"/>
<constructor-arg value="#{ T(com.vladmihalcea.flexypool.adaptor.HikariCPPoolAdapter).FACTORY }"/>
</bean>
<bean id="configuration" factory-bean="configurationBuilder" factory-method="build"/>
<bean id="flexyPoolDataSource" class="com.vladmihalcea.flexypool.FlexyPoolDataSource" init-method="start" destroy-method="stop">
<constructor-arg ref="configuration"/>
<constructor-arg>
<array>
<bean class="com.vladmihalcea.flexypool.strategy.IncrementPoolOnTimeoutConnectionAcquiringStrategy.Factory">
<constructor-arg value="5"/>
</bean>
<bean class="com.vladmihalcea.flexypool.strategy.RetryConnectionAcquiringStrategy.Factory">
<constructor-arg value="2"/>
</bean>
</array>
</constructor-arg>
</bean>
<bean id="entityManagerFactoryGMetrics"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="flexyPoolDataSource"/>
<property name="persistenceUnitName" value="${gmetric.context.name}"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--<property name="generateDdl" value="true" />-->
<property name="databasePlatform" value="${hibernate.dialect}"/>
<property name="showSql" value="${hibernate.showSQL}"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.driver_class">${gmetric.driverClassName}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.showSQL}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
我的问题是:
- 我的
flexy-pool
基于 Spring 的(默认)配置是否正确? - 是否有解决方案来防止与
flexy-pool
相关的运行时异常? - 这是什么原因
NoSuchElementException
?
我发现 Dropwizard Metrics 4(flexy-pool
需要)在我的阴影 jar 中丢失,因此发生了这个有线运行时异常:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
根据 author,这与 flexy-pool
检测相关 Dropwizard Metrics 处理程序的方式有关(因为它支持不能互换使用的 DM3 和 DM4)。