- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我们正在尝试将 Spring-Batch 作业从 XML 配置转换为 Java 配置。我们正在使用 Spring 4.0.1.RELEASE 和 Spring Batch 2.2.1.RELEASE。
转换一项作业后,日志文件中开始出现以下警告:
15-Apr-2014 09:59:26.335 [Thread-2] WARN o.s.b.f.s.DisposableBeanAdapter - Invocation of destroy method 'close' failed on bean with name 'fileReader': org.springframework.batch.item.ItemStreamException: Error while closing item reader
完整的堆栈跟踪是:
org.springframework.batch.item.ItemStreamException: Error while closing item reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:131) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]
at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]
at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:349) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:272) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:540) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:516) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:824) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:485) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:921) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:895) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:809) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
Caused by: java.lang.IllegalStateException: EntityManager is closed
at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:132) ~[hibernate-entitymanager-4.2.5.Final.jar:4.2.5.Final]
at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]
at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:334) ~[spring-orm-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at $Proxy67.close(Unknown Source) ~[na:na]
at org.springframework.batch.item.database.JpaPagingItemReader.doClose(JpaPagingItemReader.java:236) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:128) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
... 13 common frames omitted
此错误仅在作业使用 Java 配置而非 XML 配置时出现。使用 XML 配置的步骤如下所示:
<batch:step id="createFile" next="insertFile">
<batch:tasklet>
<batch:chunk reader="fileReader" writer="fileWriter"
commit-interval="#{jobProperties[commit_interval]}" />
</batch:tasklet>
</batch:step>
<bean id="fileReader"
class="org.springframework.batch.item.database.JpaPagingItemReader">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="queryString"
value="select mt from MyTable mt where status in ('1','2','3')" />
<property name="pageSize" value="1000" />
</bean>
Java 配置为:
@Bean
public Job fileProcessJob(JobBuilderFactory jobBuilders,
Step loadConfig,
Step createFile,
Step insertFile
) {
return jobBuilders.get(moduleName)
.start(loadConfig)
.next(createFile)
.next(insertFile)
.build()
.build();
}
@Bean
public ItemReader<MyTable> cetFileReader(EntityManagerFactory entityManagerFactory) {
JpaPagingItemReader<MyTable> itemReader = new JpaPagingItemReader<MyTable>();
itemReader.setEntityManagerFactory(entityManagerFactory);
itemReader.setQueryString("select mt from MyTable mt where status in ('1','2','3')");
itemReader.setPageSize(1000);
return itemReader;
}
为什么在使用 Java 配置而不是 XML 配置时,日志中会出现此警告?
最佳答案
TLDR;
Spring 尝试在使用 Java 配置时自动推断 destroyMethod
(但在使用 XML 配置时不会这样做)。要禁用此自动推理,请使用:
@Bean(destroyMethod="")
答案在@Bean
注解的JavaDoc中;特别是关于 org.springframework.context.annotation.Bean.destroyMethod()
方法(强调我的):
The optional name of a method to call on the bean instance upon closing the application context, for example a close() method on a JDBC DataSource implementation, or a Hibernate SessionFactory object. The method must have no arguments but may throw any exception.
As a convenience to the user, the container will attempt to infer a destroy method against an object returned from the @Bean method. For example, given a @Bean method returning an Apache Commons DBCP BasicDataSource, the container will notice the close() method available on that object and automatically register it as the destroyMethod. This 'destroy method inference' is currently limited to detecting only public, no-arg methods named 'close'. The method may be declared at any level of the inheritance hierarchy and will be detected regardless of the return type of the @Bean method (i.e., detection occurs reflectively against the bean instance itself at creation time).
To disable destroy method inference for a particular @Bean, specify an empty string as the value, e.g. @Bean(destroyMethod=""). Note that the org.springframework.beans.factory.DisposableBean and the java.io.Closeable/java.lang.AutoCloseable interfaces will nevertheless get detected and the corresponding destroy/close method invoked.
Note: Only invoked on beans whose lifecycle is under the full control of the factory, which is always the case for singletons but not guaranteed for any other scope.
将Java配置更改为:
@Bean(destroyMethod="")
public ItemReader<MyTable> cetFileReader(EntityManagerFactory entityManagerFactory) {
JpaPagingItemReader<MyTable> itemReader = new JpaPagingItemReader<MyTable>();
itemReader.setEntityManagerFactory(entityManagerFactory);
itemReader.setQueryString("select mt from MyTable mt where status in ('1','2','3')");
itemReader.setPageSize(1000);
return itemReader;
}
警告不再出现。我可以通过在 org.springframework.beans.factory.support.DisposableBeanAdapter.destroy()
方法上放置一个断点并启动 XML 配置的作业和 Java 配置的作业来确认这一点。
对于 XML 配置:
对于 Java 配置(未设置 destroyMethod=""
):
对于 Java 配置(带有 destroyMethod=""
集):
基于这些观察,我得出结论,容器在通过 XML 配置时不会尝试推断销毁方法;但它在通过 Java 配置时确实如此。这就是为什么会针对 Java 配置而不是 XML 配置显示警告的原因。
另外,容器推断的方法destroyMethod似乎来自org.springframework.batch.item.ItemStreamSupport.close()
。因此,这可能发生在任何实现通过 @Bean
注释配置的 ItemStreamSupport
接口(interface)的 bean 上。
注释已添加到 Spring Framework Reference material for @Bean描述这种行为:
By default, beans defined using Java config that have a public close or shutdown method are automatically enlisted with a destruction callback. If you have a public close or shutdown method and you do not wish for it to be called when the container shuts down, simply add @Bean(destroyMethod="") to your bean definition to disable the default (inferred) mode.
关于java - 为什么使用 Java 配置配置的 JPAPagingItemReader 的销毁方法 'close' 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23089159/
我有一个 Spring 批处理进程,它从 SQL Server 读取数据并写入文件。我使用的查询返回 350000 行,在 SQL Server studio 上运行大约需要 2 分钟 - 因此该查询
我一直在尝试了解 Spring 批处理实际上是如何初始化状态的,但我找不到相当明显的东西。 当步骤配置为具有JpaPagingItemReader时,我相信数据是作为页面从数据库读取的。我可以在实现中
我需要确定 14 条记录的范围。 block 大小为 10 页面大小为 2。它的范围仅限于 10 条记录。 我用不同的方式检查过。 block 大小 = 5 页面大小 = 10仍然只限定了 10 条记
我们正在尝试将 Spring-Batch 作业从 XML 配置转换为 Java 配置。我们正在使用 Spring 4.0.1.RELEASE 和 Spring Batch 2.2.1.RELEASE。
我正在尝试使用 JpaPagingItemReader 执行 native SELECT 查询。但是,当我运行它时,一些记录从我的数据库中删除(我使用 mysql 控制台在批处理作业执行之前和之后检查
在 Spring Batch 作业运行之前。我有一个导入表,其中包含需要导入到我们系统中的所有项目。此时已验证它仅包含我们系统中不存在的项目。 接下来我有一个 Spring Batch 作业,它使用
我是一名优秀的程序员,十分优秀!