使用 camel exec 组件调用批处理文件时获取 IOException

Getting IOException while using camel exec component to invoke a batch file

我正在使用 camel's exec component 的基本实现在 windows 环境中调用批处理文件。每当批处理文件执行失败并且 returns 非零退出代码以及一些错误消息时,我的路由工作正常。但是只要执行成功,就会抛出如下IOException。

org.apache.camel.component.exec.ExecException: Unable to execute command ExecCommand [args=[/C, d:\file.bat, test_request.xml, null], executable=cmd, timeout=5000, outFile=null, workingDir=null, useStderrOnEmptyStdout=false]
at org.apache.camel.component.exec.impl.DefaultExecCommandExecutor.execute(DefaultExecCommandExecutor.java:81)
at org.apache.camel.component.exec.ExecProducer.process(ExecProducer.java:46)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.jetty.CamelContinuationServlet.service(CamelContinuationServlet.java:150)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:503)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:429)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:366)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: Stream Closed
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.FilterOutputStream.close(Unknown Source)
    at org.apache.commons.exec.DefaultExecutor.closeStreams(DefaultExecutor.java:288)
    at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:364)
    at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:160)
    at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:147)
    at org.apache.camel.component.exec.impl.DefaultExecCommandExecutor.execute(DefaultExecCommandExecutor.java:67)
    ... 30 more

奇怪的是,每当我从 eclipse IDE 中 运行 我的 jar 时,一切正常。但是每当我使用 "java -jar" 从命令提示符部署它时,它只会在批处理文件处理成功完成的情况下给我上述异常。做了大量的研究让我知道这个问题与 java 运行time 使用的流有关,但我无法找到根本原因。我尝试在 camel exec 中使用 ExecBinding.EXEC_COMMAND_OUT_FILE 提供输出文件,但这并没有解决我的问题。

问题出在我调用 camel exec 的方式上。我用的是 -

cmd /C <path_to_batch_file> param

深入研究问题后,我意识到 /C 会创建一个新的命令提示符实例,执行它然后销毁进程。这是在某处关闭流并导致骆驼抛出异常。解决方案是使用 /K 开关,它将 return 控制权交给运行时。

cmd /K <path_to_batch_file> param