cannot be cast to org.springframework.core.io.WritableResource on Spring AWS example

泪湿孤枕 提交于 2020-03-22 10:22:44

问题


I'm reading this documentation:

http://cloud.spring.io/spring-cloud-aws/spring-cloud-aws.html

on using AWS from a Spring application. I'm particularly interested in S3, so, I set up the application and copied this snippet of code to make sure the set up is working correctly:

Resource resource = this.resourceLoader.getResource("s3://myBucket/rootFile.log");
WritableResource writableResource = (WritableResource) resource;
try (OutputStream outputStream = writableResource.getOutputStream()) {
  outputStream.write("test".getBytes());
}

but when I run it, I get this error:

java.lang.ClassCastException: org.springframework.web.context.support.ServletContextResource cannot be cast to org.springframework.core.io.WritableResource

Any ideas what's wrong? is that a setup problem? It doesn't look like to me, but I'm new to this.


回答1:


I had to remove

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

from my dependencies.

When devtools is included, inside the GenericApplicationContext.getResources() method it executes the if block, but without devtools it calls the super.getResource():

public Resource getResource(String location) {
    if (this.resourceLoader != null) {
        return this.resourceLoader.getResource(location);
    }
    return super.getResource(location);
}

This will use the s3 protocol handler and give you a different type of Resource that does implement WritableResource.




回答2:


Try declaring/casting Resource class as FileSystemResource instead:

FileSystemResource resource = this.resourceLoader.getResource("s3://myBucket/rootFile.log");
WritableResource writableResource = (WritableResource) resource;
try (OutputStream outputStream = writableResource.getOutputStream()) {
  outputStream.write("test".getBytes());
}



回答3:


I have the same issue, turn out that I am using the wrong lib. Try to change dependency from

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-aws</artifactId>
    </dependency>

To

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-aws</artifactId>
    </dependency>

Also do not forget to add aws config in application.yml, otherwise it won't start.

cloud.aws:
    region.static: your-region
    credentials:
      accessKey: your-key
      secretKey: your-secret

Hope this can solve your problem.




回答4:


I've tried to follow the solution proposed by @accresse, but without success. My only way of solving it was declaring a new SimpleStorageProtocolResolver and adding it as a ProtocolResolver to the DefaultResourceLoader. Using Spring Boot 2.1.7 e Spring Cloud Aws 2.1.4.

@Autowired
public void configureResourceLoader(AmazonS3 amazonS3, DefaultResourceLoader resourceLoader) {
    SimpleStorageProtocolResolver simpleStorageProtocolResolver = new SimpleStorageProtocolResolver(amazonS3);
    // As we are calling it by hand, we must initialize it properly.
    simpleStorageProtocolResolver.afterPropertiesSet();
    resourceLoader.addProtocolResolver(simpleStorageProtocolResolver);
}

Links to follow:

  • https://github.com/spring-cloud/spring-cloud-aws/issues/348
  • https://github.com/spring-cloud/spring-cloud-aws/issues/384
  • https://github.com/spring-projects/spring-boot/issues/9331


来源:https://stackoverflow.com/questions/47135265/cannot-be-cast-to-org-springframework-core-io-writableresource-on-spring-aws-exa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!