我有以下作家类原型:
public class MyWriter extends AbstractItemStreamItemWriter<FieldSet> {
...
@Override
public void close()
{
...
{
...
}
我的工作由这些@Beans
:
@Bean
protected Step step(ItemReader<FieldSet> reader, ItemWriter<FieldSet> writer)
{
return stepBuilder.get("step")
.<FieldSet, FieldSet> chunk(chunkSize)
.reader(reader)
.writer(writer)
.listener(this)
.build();
}
@Bean
protected Job myImportJob(Step step, JobExecutionListener jobExecutionListener)
{
return jobBuilder
.get("myImportJob")
.listener(jobExecutionListener)
.start(step)
.build();
}
作业是从MQ侦听器触发的,如下所示:
@Autowired
private Job job;
@Autowired
private JobLauncher jobLauncher;
@JmsListener(destination = "queue_name")
public void receiveMessage(TextMessage message) throws JMSException
{
log.warn("Received message {} with listener {}.", message, this);
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
// add job parameters here
...
JobParameters jobParameters = jobParametersBuilder.toJobParameters();
try
{
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
log.trace("jobExecution = " + jobExecution);
}
catch (JobExecutionException jee)
{
log.warn("Could not run job {}", job);
}
}
我遇到的问题是MyWriter的close方法被调用两次。每个调用的堆栈跟踪是:
Thread [DefaultMessageListenerContainer-2] (Suspended (breakpoint at line 162 in MyWriter))
MyWriter.close() line: 162
MyWriter$$FastClassBySpringCGLIB$$80508a22.invoke(int, Object, Object[]) line: not available
MethodProxy.invoke(Object, Object[]) line: 204
CglibAopProxy$CglibMethodInvocation.invokeJoinpoint() line: 720
CglibAopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 157
DelegatingIntroductionInterceptor.doProceed(MethodInvocation) line: 133
DelegatingIntroductionInterceptor.invoke(MethodInvocation) line: 121
CglibAopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 179
CglibAopProxy$DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 655
MyWriter$$EnhancerBySpringCGLIB$$e345242b.close() line: not available
CompositeItemStream.close() line: 85
TaskletStep.close(ExecutionContext) line: 305
TaskletStep(AbstractStep).execute(StepExecution) line: 271
--> SimpleStepHandler.handleStep(Step, JobExecution) line: 148
SimpleJob(AbstractJob).handleStep(Step, JobExecution) line: 392
SimpleJob.doExecute(JobExecution) line: 135
SimpleJob(AbstractJob).execute(JobExecution) line: 306
SimpleJobLauncher$1.run() line: 135
SyncTaskExecutor.execute(Runnable) line: 50
SimpleJobLauncher.run(Job, JobParameters) line: 128
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 497
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 302
ReflectiveMethodInvocation.invokeJoinpoint() line: 190
ReflectiveMethodInvocation.proceed() line: 157
SimpleBatchConfiguration$PassthruAdvice.invoke(MethodInvocation) line: 127
ReflectiveMethodInvocation.proceed() line: 179
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 208
$Proxy105.run(Job, JobParameters) line: not available
MyMQListener$$EnhancerBySpringCGLIB$$28277c0e(MyMQListener).receiveMessage(TextMessage) line: 74
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 497
InvocableHandlerMethod.doInvoke(Object...) line: 198
InvocableHandlerMethod.invoke(Message<?>, Object...) line: 116
MessagingMessageListenerAdapter.invokeHandler(Message, Session, Message<?>) line: 90
MessagingMessageListenerAdapter.onMessage(Message, Session) line: 66
DefaultMessageListenerContainer(AbstractMessageListenerContainer).doInvokeListener(SessionAwareMessageListener, Session, Message) line: 721
DefaultMessageListenerContainer(AbstractMessageListenerContainer).invokeListener(Session, Message) line: 681
DefaultMessageListenerContainer(AbstractMessageListenerContainer).doExecuteListener(Session, Message) line: 651
DefaultMessageListenerContainer(AbstractPollingMessageListenerContainer).doReceiveAndExecute(Object, Session, MessageConsumer, TransactionStatus) line: 315
DefaultMessageListenerContainer(AbstractPollingMessageListenerContainer).receiveAndExecute(Object, Session, MessageConsumer) line: 253
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener() line: 1150
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop() line: 1142
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run() line: 1039
Thread.run() line: 745
和
Thread [DefaultMessageListenerContainer-2] (Suspended (breakpoint at line 162 in MyWriter))
MyWriter.close() line: 162
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 497
DisposableBeanAdapter.invokeCustomDestroyMethod(Method) line: 354
DisposableBeanAdapter.destroy() line: 277
DisposableBeanAdapter.run() line: 236
StepContext.close() line: 213
StepSynchronizationManager$1.close(StepContext) line: 53
StepSynchronizationManager$1.close(Object) line: 36
StepSynchronizationManager$1(SynchronizationManagerSupport<E,C>).release() line: 190
StepSynchronizationManager.release() line: 112
TaskletStep(AbstractStep).doExecutionRelease() line: 290
TaskletStep(AbstractStep).execute(StepExecution) line: 278
--> SimpleStepHandler.handleStep(Step, JobExecution) line: 148
SimpleJob(AbstractJob).handleStep(Step, JobExecution) line: 392
SimpleJob.doExecute(JobExecution) line: 135
SimpleJob(AbstractJob).execute(JobExecution) line: 306
SimpleJobLauncher$1.run() line: 135
SyncTaskExecutor.execute(Runnable) line: 50
SimpleJobLauncher.run(Job, JobParameters) line: 128
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 497
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 302
ReflectiveMethodInvocation.invokeJoinpoint() line: 190
ReflectiveMethodInvocation.proceed() line: 157
SimpleBatchConfiguration$PassthruAdvice.invoke(MethodInvocation) line: 127
ReflectiveMethodInvocation.proceed() line: 179
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 208
$Proxy105.run(Job, JobParameters) line: not available
MyMQListener$$EnhancerBySpringCGLIB$$28277c0e(MyMQListener).receiveMessage(TextMessage) line: 74
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 497
InvocableHandlerMethod.doInvoke(Object...) line: 198
InvocableHandlerMethod.invoke(Message<?>, Object...) line: 116
MessagingMessageListenerAdapter.invokeHandler(Message, Session, Message<?>) line: 90
MessagingMessageListenerAdapter.onMessage(Message, Session) line: 66
DefaultMessageListenerContainer(AbstractMessageListenerContainer).doInvokeListener(SessionAwareMessageListener, Session, Message) line: 721
DefaultMessageListenerContainer(AbstractMessageListenerContainer).invokeListener(Session, Message) line: 681
DefaultMessageListenerContainer(AbstractMessageListenerContainer).doExecuteListener(Session, Message) line: 651
DefaultMessageListenerContainer(AbstractPollingMessageListenerContainer).doReceiveAndExecute(Object, Session, MessageConsumer, TransactionStatus) line: 315
DefaultMessageListenerContainer(AbstractPollingMessageListenerContainer).receiveAndExecute(Object, Session, MessageConsumer) line: 253
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener() line: 1150
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop() line: 1142
DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run() line: 1039
Thread.run() line: 745
堆栈中的最后一个公共行是SimpleStepHandler.handleStep(Step, JobExecution) line: 148
,用箭头标记。
我目前有一个特殊的类级布尔变量,只存在以确保close方法的内核只运行一次,但这对我来说似乎不太合适。
阅读或写作没有例外或问题。这不是由于跳过或重新启动功能。
如何防止ItemWriter.close()方法被调用两次?
答案 0 :(得分:1)
由于这个错误,我头疼得很厉害。
Spring尝试在使用Java配置时自动推断一个destroyMethod(但在使用XML配置时却不这样做)。要禁用此自动推断,请使用:
from copy import deepcopy
empty = []
for x in range(2):
empty.append([])
for y in range(2):
empty[x].append(False)
status = {k:[] for k in ["a", "b", "c"]}
status["a"] = deepcopy(empty)
status["b"] = deepcopy(empty)
status["c"] = deepcopy(empty)
print(status)
status["a"][0][0] = True
print(status)
现在使用此注释Spring停止两次调用我的方法,并且只会 由Spring批处理调用一次。