【问题标题】:File name contains # caused Spring Batch StaxEventItemReader failed to open文件名包含 # 导致 Spring Batch StaxEventItemReader 无法打开
【发布时间】:2016-01-11 16:46:51
【问题描述】:

我有一个名称中带有 # 的输入文件 (UPX#L.xxxxx001.xml)。 Spring Batch StaxEventItemReader 无法打开此文件。有没有办法逃脱这个特殊字符?请指教。

这是我的豆

 <bean id="myItemReader" parent="myItemReaderParent" scope="step">

        <property name="resource" value="file:#{jobParameters['toolf.input.file.name']}"/>

 </bean>

<bean id="myItemReaderParent" class="org.springframework.batch.item.xml.StaxEventItemReader" scope="prototype">

    <property name="fragmentRootElementName" value="MyRec"/>

    <property name="unmarshaller" ref="myUnmarshaller"/>

</bean>
[INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,487] - Sending notification for start of JobExecution: id=52760, version=1, startTime=Thu Feb 05 10:27:23 EST
 2015, endTime=null, lastUpdated=Thu Feb 05 10:27:23 EST 2015, status=STARTED, exitStatus=exitCode=UNKNOWN;exitDescription=, job=[JobInstance: id=52759, version=0, JobParameters=[

{toolf.institutionSymbol=YDX , toolf.projectId=013832, toolf.orderId=678161, toolf.transmissionDate=20150205 10:27:23.392 EST, toolf.input.file.name=/batchdata/dataload/xxx/in/tool/UPX#L.xxxxx001.xml, toolf.out.root.directory=/batchdata/output, toolf.out.input.file.name.without.path=YDX.013832.678161.YbpUsSI#Picklists.d20150204.t140001.xml, toolf.out.working.directory/batchdata/dataload/xxx/in/tool/, timestamp=1423150043392}

], Job=[timeOfOrderLabelJob]]
[INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,576] - Executing step: [toolPrologue]
[ERROR]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,607] - Encountered an error executing the step
 org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
 at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:137)
 at sun.reflect.GeneratedMethodAccessor260.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
 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 $Proxy9.open(Unknown Source)
 at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:93)
 at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:301)
 at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:192)
 at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
 at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
 at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
 at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
 at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
 at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
 at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
 at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
 at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
 at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:229)
 at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129)
 at org.oclc.tool.mule.launch.MuleJobLauncher.launchJob(MuleJobLauncher.groovy:74)
 at org.oclc.tool.mule.launch.JobLauncher$launchJob.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:137)
 at org.oclc.tool.mule.si.JmsMessageUnwrapper.unwrapMessage(JmsMessageUnwrapper.groovy:42)
 at sun.reflect.GeneratedMethodAccessor596.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69)
 at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:83)
 at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
 at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
 at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
 at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126)
 at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:225)
 at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:125)
 at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:73)
 at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:64)
 at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:98)
 at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
 at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:110)
 at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
 at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:61)
 at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
 at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
 at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
 at org.springframework.integration.core.MessagingTemplate.convertAndSend(MessagingTemplate.java:189)
 at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:183)
 at org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate.send(ChannelPublishingJmsMessageListener.java:424)
 at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:278)
 at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:535)
 at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:495)
 at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)
 at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
 at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
 at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)
 at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050)
 at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)
 at java.lang.Thread.run(Thread.java:619)
 Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode)
 at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:182)
 at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:134)
 ... 73 more
[INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,612] - enter DetailLogStepExecutionListener.afterStep
[INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,612] - exit DetailLogStepExecutionListener.afterStep

【问题讨论】:

  • 你的问题是#?错误是“输入资源必须存在”。
  • 是的。这是#问题。删除 # 后,它就可以正常工作了。
  • 我认为你可以像
    &lt;property name="resource" value="#{T(java.lang.URI).create("file:{jobParameters['toolf.input.file.name']}").toURL()}"/&gt;
    这样的方式使用spEL

标签: java linux spring spring-batch


【解决方案1】:

URL/URI 中,# 字符被保留,用于分隔fragment identifier(这对file: 资源方案没有意义)。如果您想将此字符包含在路径中,则必须使用 %23 对其进行转义

建议您将参数指定为完整的 URI/URI,而不是文件系统路径,而不是将您的值连接到 bean 定义文件中的 file:

<property name="resource" value="#{jobParameters['toolf.input.file.url']}"/>

并将toolf.input.file.url 设置为:

file:/batchdata/dataload/xxx/in/tool/UPX%23L.xxxxx001.xml

这将避免您可能遇到的任何其他擒纵装置陷阱,例如字符 @!= 等。

如果你必须使用文件系统路径作为参数,你应该可以使用:

<property name="resource" value="#{new java.io.File(jobParameters['toolf.input.file.name']).toURI().toURL()}"/>

【讨论】:

  • if (fileName.contains("#")) { def (value1, value2) = fileName.split("#") fileName = value1 + "%23#" + value2 } 我试过这个.还是不行
  • 应该是“%23”而不是“%23#”
【解决方案2】:

通过查看您的错误消息和回复,您的问题很清楚,Tunaki 和 Glenn Lane 都部分正确,我赞成 Glenn Lane 回答了您提出的问题,并且做得很好。

来自您对格伦的回复:

if (fileName.contains("#")) { def (value1, value2) = fileName.split("#") fileName = value1 + "%23#" + value2 } 我试过了。还是不行

逃跑无济于事。

角色已经在执行链的某个地方被处理,Tunaki 对你遇到的类型错误的质疑是正确的。

来自您的错误日志:

[ERROR]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,607] - 执行步骤时遇到错误 org.springframework.batch.item.ItemStreamException: 初始化阅读器失败

再加上Tunaki指出的资源状态异常,我们可以断定确实如此。这里没有足够的信息来说明发生这种情况的原因或地点,但这里有两个一般类别:

  1. 根据它到达或来自文件存储的方式,该字符可能已经从文件中删除,或者在存储中以文件处理程序无法处理的方式别名。出于格伦指出的原因。

  2. 根据执行链中的消息或作业处理,当它转换为 URI/URL 调用或转换为 URI/URL 调用时,它会被剥离。由于格伦指出的原因。

是的。这是#问题。删除 # 后,它就可以正常工作了。

基于上述陈述,简单、快速和肮脏的解决方案是意识到这一点,并根据需要通过直接从文件或 uri 中剥离和注入 # 来处理它。根据您的代码 sn-p,您知道如何执行此操作。

解决此问题的正确方法是跟踪资源错误发生的位置,并确保您的文件处理在整个作业流程中保持一致。

如果没有所有正确的代码和/或了解更多关于您的系统配置的信息,我无法具体说明。 bean 和错误日志之间没有足够的信息来准确说明发生的位置,只是这正是您的问题。

以下是一些可能的建议:

我假设您已经直接检查了文件 Store 并手动删除了 # 并更改了作业中的文件名并运行,根据您的上述声明。

  1. 尝试使用相同的标识符从不同的 java 对象访问存储中的文件,它可以工作;然后检查您的项目阅读器实现如何处理文件访问。

  2. 如果失败或者那不是失败点。检查“#”值是否是作业文件,以及它是否存在和/或执行拆分时唯一的 #。

  3. 如果所有检查都发现它是如何到达文件存储的,并且该资源可以在存储中正确定位,并且 # 在您的实现中也未保留或需要特殊处理/配置。

这将有助于缩小根本原因。

【讨论】:

    猜你喜欢
    • 2013-01-13
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多