捕获异常时抑制堆栈跟踪
Suppressing stack trace when catching exception
我有一个简短的 2 步 Spring 批处理作业,它在严格模式下使用 StaxEventItemReader 从 xml 休息服务调用中读取。我希望它处于严格模式,因为如果无法连接到其余服务,就没有理由继续。我想捕获异常并使用自定义消息优雅地退出,而不是使用堆栈跟踪。
我能够使用带有 afterStep() 方法的 StepExecutionListener 来捕获异常以检查失败 (stepExecution.getFailureExceptions()),但堆栈跟踪仍在输出。我收到我的自定义消息(下面 STS 输出中的 13:05:32,981)和堆栈跟踪。当我将 ItemReaderListener 与 onError 方法一起使用时,没有调用 onError 方法,我猜是因为它是初始化异常而不是读取错误。
捕获初始化失败reader异常并抑制输出堆栈跟踪的最佳方法是什么?
Spring批处理作业:
<batch:job id="randomSends2NG">
<batch:step id="getStations" next="generateAndSend">
<batch:tasklet>
<batch:chunk reader="getStationsFromNG_RestXML"
processor="idExtractor"
writer="stationsWriter"
commit-interval="1">
</batch:chunk>
<batch:listeners>
<batch:listener ref="noStationsStopListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
<batch:step id="generateAndSend">
<batch:tasklet>
<batch:chunk reader="readStationIdsList"
processor="createRandomRequests"
writer="ngBroadcasterService"
commit-interval="400">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
带堆栈跟踪的 STS 输出:
13:05:30,479 [main] INFO SimpleJobLauncher - No TaskExecutor has been set, defaulting to synchronous executor.
13:05:30,776 [main] INFO DepartmentSendCountsNoOpReader - constructing stationSendCountsReader
LightYellow color:43
13:05:31,368 [main] INFO ProcessStatisticsTasklet - constructor...
13:05:31,525 [main] INFO RequestsListReader - constructing requestsListReader
13:05:31,588 [main] INFO Jaxb2Marshaller - Creating JAXBContext with classes to be bound [class com.pevco.pevcotubesystem.StationConfig]
13:05:31,886 [main] INFO SimpleJobLauncher - Job: [FlowJob: [name=randomSends2NG]] launched with the following parameters: [{hostNameOrIP=192.168.100.10:8383}]
13:05:31,902 [main] INFO SimpleStepHandler - Executing step: [getStations]
13:05:32,981 [main] ERROR AbstractStep - Encountered an error executing step getStations in job randomSends2NG
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:147)
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:497)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy8.open(Unknown Source)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:96)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:310)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:135)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode)
at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:195)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144)
... 27 more
13:05:32,981 [main] ERROR NoStationsStopListener - Not able to get stations list from NG. Check that NG is running
13:05:32,998 [main] INFO SimpleJobLauncher - Job: [FlowJob: [name=randomSends2NG]] completed with the following parameters: [{hostNameOrIP=192.168.100.10:8383}] and the following status: [FAILED]
13:05:32,998 [main] INFO ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@4f4a7090: startup date [Wed Jul 01 13:05:29 EDT 2015]; root of context hierarchy
当遇到这个问题时,最好的解决方案可能是尽快检查 REST 服务,因为 "without the ability to connect to the rest service, there is no reason to continue [...] and exit gracefully with a custom message".
在第一步之前使用 JobExecutionDecider 检查 REST 可用性并根据服务 presence/absence.
继续或结束您的工作
我有一个简短的 2 步 Spring 批处理作业,它在严格模式下使用 StaxEventItemReader 从 xml 休息服务调用中读取。我希望它处于严格模式,因为如果无法连接到其余服务,就没有理由继续。我想捕获异常并使用自定义消息优雅地退出,而不是使用堆栈跟踪。
我能够使用带有 afterStep() 方法的 StepExecutionListener 来捕获异常以检查失败 (stepExecution.getFailureExceptions()),但堆栈跟踪仍在输出。我收到我的自定义消息(下面 STS 输出中的 13:05:32,981)和堆栈跟踪。当我将 ItemReaderListener 与 onError 方法一起使用时,没有调用 onError 方法,我猜是因为它是初始化异常而不是读取错误。
捕获初始化失败reader异常并抑制输出堆栈跟踪的最佳方法是什么?
Spring批处理作业:
<batch:job id="randomSends2NG">
<batch:step id="getStations" next="generateAndSend">
<batch:tasklet>
<batch:chunk reader="getStationsFromNG_RestXML"
processor="idExtractor"
writer="stationsWriter"
commit-interval="1">
</batch:chunk>
<batch:listeners>
<batch:listener ref="noStationsStopListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
<batch:step id="generateAndSend">
<batch:tasklet>
<batch:chunk reader="readStationIdsList"
processor="createRandomRequests"
writer="ngBroadcasterService"
commit-interval="400">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
带堆栈跟踪的 STS 输出:
13:05:30,479 [main] INFO SimpleJobLauncher - No TaskExecutor has been set, defaulting to synchronous executor.
13:05:30,776 [main] INFO DepartmentSendCountsNoOpReader - constructing stationSendCountsReader
LightYellow color:43
13:05:31,368 [main] INFO ProcessStatisticsTasklet - constructor...
13:05:31,525 [main] INFO RequestsListReader - constructing requestsListReader
13:05:31,588 [main] INFO Jaxb2Marshaller - Creating JAXBContext with classes to be bound [class com.pevco.pevcotubesystem.StationConfig]
13:05:31,886 [main] INFO SimpleJobLauncher - Job: [FlowJob: [name=randomSends2NG]] launched with the following parameters: [{hostNameOrIP=192.168.100.10:8383}]
13:05:31,902 [main] INFO SimpleStepHandler - Executing step: [getStations]
13:05:32,981 [main] ERROR AbstractStep - Encountered an error executing step getStations in job randomSends2NG
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:147)
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:497)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy8.open(Unknown Source)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:96)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:310)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:135)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode)
at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:195)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144)
... 27 more
13:05:32,981 [main] ERROR NoStationsStopListener - Not able to get stations list from NG. Check that NG is running
13:05:32,998 [main] INFO SimpleJobLauncher - Job: [FlowJob: [name=randomSends2NG]] completed with the following parameters: [{hostNameOrIP=192.168.100.10:8383}] and the following status: [FAILED]
13:05:32,998 [main] INFO ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@4f4a7090: startup date [Wed Jul 01 13:05:29 EDT 2015]; root of context hierarchy
当遇到这个问题时,最好的解决方案可能是尽快检查 REST 服务,因为 "without the ability to connect to the rest service, there is no reason to continue [...] and exit gracefully with a custom message".
在第一步之前使用 JobExecutionDecider 检查 REST 可用性并根据服务 presence/absence.