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

Viewed 3660

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.

4 Answers

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.

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:

Related