在 Spring Boot Batch 项目中,出现以下错误,不确定这里发生了什么问题?
我只是从mysql DB中读取表,然后使用FlatFileItemWriter将其写入文件。还使用Partiontioner读取代码并将其写入平面文件。 Spring Boot Parent
版本2.0.2.RELEASE
。
org.springframework.batch.item.ItemStreamException: File is not writable: [C:\Spring_Learning\spring-batch\spring-batch-classic-db\csv\outputs\users.processed201-250.csv]
at org.springframework.batch.item.util.FileUtils.setUpOutputFile(FileUtils.java:88) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter$OutputState.initializeBufferedWriter(FlatFileItemWriter.java:572) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter$OutputState.access$000(FlatFileItemWriter.java:414) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter.doOpen(FlatFileItemWriter.java:348) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter.open(FlatFileItemWriter.java:338) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter$$FastClassBySpringCGLIB$$bd919dcd.invoke(<generated>) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.batch.item.file.FlatFileItemWriter$$EnhancerBySpringCGLIB$$d3ba3d4f.open(<generated>) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:310) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:197) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:139) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:136) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_171]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_171]
代码
@Bean
@StepScope
public FlatFileItemWriter<Payments> slaveWriter(@Value("#{stepExecutionContext[fromId]}") final String fromId,
@Value("#{stepExecutionContext[toId]}") final String toId) {
FlatFileItemWriter<Payments> reader = new FlatFileItemWriter<>();
reader.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
reader.setAppendAllowed(true);
reader.setLineAggregator(new DelimitedLineAggregator<Payments>() {
{
setDelimiter(",");
setFieldExtractor(new BeanWrapperFieldExtractor<Payments>() {
{
setNames(new String[] { "customerNumber", "checkNumber", "paymentDate", "amount"});
}
});
}
});
return reader;
}
答案 0 :(得分:1)
尝试更新您的代码:
FlatFileItemWriter<Payments> writer = new FlatFileItemWriter<>();
writer.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
writer.setAppendAllowed(true);
收件人:
FlatFileItemWriter<Payments> writer = new FlatFileItemWriter<>();
writer.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
writer.setAppendAllowed(true);
writer.setShouldDeleteIfEmpty(true);
writer.setShouldDeleteIfExists(true);
我有同样的错误,对我有用。
有关详细信息,这是因为restarted
的{{1}}参数可以在作业重新启动时设置为FileUtils.setUpOutputFile(File file, boolean restarted, boolean append, boolean overwriteOutputFile)
。文件是从旧上下文中恢复的,并且不可写...
我不知道为什么。
答案 1 :(得分:0)
来自
的例外if (!file.canWrite()) {
throw new ItemStreamException("File is not writable: [" + file.getAbsolutePath() + "]");
}
File.canWrite如下 因此,请检查包括父母在内的路径,如果他们都具有“写”访问权限
/**
138: * This method test whether or not the current thread is allowed to
139: * write to this object. This will be true if and only if 1) The
140: * <code>SecurityManager</code> (if any) allows write access to the
141: * file and 2) The file exists and 3) The file is writable. To determine
142: * whether or not a non-existent file can be created, check the parent
143: * directory for write access.
144: *
145: * @return <code>true</code> if writing is allowed, <code>false</code>
146: * otherwise
147: *
148: * @exception SecurityException If the <code>SecurityManager</code>
149: * does not allow access to the file
150: */
151: public boolean canWrite()
152: {
153: // First do a SecurityCheck before doing anything else.
154: checkWrite();
155:
156: // Test for existence. This is required by the spec
157: if (! VMFile.exists(path))
158: return false;
159:
160: if (VMFile.isDirectory(path))
161: return VMFile.canWriteDirectory(this);
162: else
163: return VMFile.canWrite(path);
164: }