java.lang.IllegalStateException: InputStream уже прочитан - не используйте InputStreamResource, если поток должен быть прочитан несколько раз - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь прочитать файл из корзины aws s3 и установить его как ресурс в моем классе Spring Batch Reader.Когда я тестирую приложение на лямбда-функции aws, я получаю ошибку ниже.какие-либо предложения экспертов?

    Caused by: java.lang.IllegalStateException: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times
    at org.springframework.core.io.InputStreamResource.getInputStream(InputStreamResource.java:97) ~[task/:na]
    at org.springframework.batch.item.file.DefaultBufferedReaderFactory.create(DefaultBufferedReaderFactory.java:34) ~[task/:na]
    at org.springframework.batch.item.file.FlatFileItemReader.doOpen(FlatFileItemReader.java:266) ~[task/:na]
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:146) ~[task/:na]

Class to read from s3 bucket
@Service
public class S3BucketProcessing {
private static final AmazonS3 s3 = AmazonS3ClientBuilder.standard().build();

public InputStreamResource readFile() throws IOException{

   String bucketName = "mybuckey";
   String key = "File.txt";

   S3Object object = s3.getObject(new GetObjectRequest(bucketName, key));    

   return new InputStreamResource(object.getObjectContent());

}

Весенний пакетный ридер класса

    @Component
public class MyReader extends FlatFileItemReader<MyEntity> {

    MyLineMapper mapper;
    MyTokenizer tokenizer;
    S3BucketProcessing s3BucketProcessing;

    @Autowired
    public MyReader(MyTokenizer tokenizer, MyLineMapper mapper, S3BucketProcessing s3BucketProcessing) throws Exception{
        LOG.info("CardCustomerNotificationReader constructor");
        this.mapper = mapper;
        this.tokenizer = tokenizer;
        this.s3BucketProcessing= s3BucketProcessing;
        this.setResource(s3BucketProcessing.readFile());
        mapper.setLineTokenizer(tokenizer);
        this.setLineMapper(mapper);
    }
}

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

В документах предлагается использовать ByteArrayResource для кэширования содержимого в памяти, а не InputStreamResource.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/InputStreamResource.html

Просто измените возвращаемую часть следующим образом:

//As suggested by berzerk
byte[] content = IOUtils.toByteArray(object.getObjectContent()); 

//Then
return new ByteArrayResource( content );
0 голосов
/ 17 ноября 2018

Вместо того, чтобы возвращать InputStreamResource, вы должны возвращать содержимое потока, может быть байтом [].
byte [] content = IOUtils.toByteArray (object.getObjectContent ()); возврат содержимого;

...