I was using Spring batch (3.1.0) for my project. The requirement is to write the output file directly to GCP bucket. Using a custom writer:
public class GSWriter implements ItemWriter<String> {
private ResourceLoader resourceLoader;
private WritableResource resource;
public GSWriter(ResourceLoader resourceLoader, String resource) {
this.resourceLoader = resourceLoader;
this.resource = (WritableResource) this.resourceLoader.getResource(resource);
}
@Override
public void write(Chunk<? extends String> items) throws Exception {
try (OutputStream outputStream = resource.getOutputStream()) {
items.forEach((item) -> {
try {
outputStream.write(item.getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
}
When I pass the resource URL(gs://{BUCKET_NAME}/{file.csv})
, I get the ClassCastException
.
java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.equifax.dfca.cdms.configuration.GSWriter]:
Factory method 'writer' threw exception with message:
class org.springframework.web.context.support.ServletContextResource cannot be cast to
class org.springframework.core.io.WritableResource
(org.springframework.web.context.support.ServletContextResource and
org.springframework.core.io.WritableResource are in unnamed module of loader 'app')
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:171)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
... 25 common frames omitted
Caused by: java.lang.ClassCastException:
class org.springframework.web.context.support.ServletContextResource cannot be cast to
class org.springframework.core.io.WritableResource
(org.springframework.web.context.support.ServletContextResource and
org.springframework.core.io.WritableResource are in unnamed module of loader 'app')
at ...
Import the dependency,
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-storage</artifactId>
</dependency>
use this bean for the resource object,
import com.google.cloud.spring.storage.GoogleStorageResource;
@Bean
public GoogleStorageResource getResource() {
Storage storage = StorageOptions.newBuilder().setProjectId(PROJECT_ID).build().getService();
return new GoogleStorageResource(storage, "gs://" + BUCKET_NAME + "/" + filname.txt);
}
In custom writer,
public class GSWriter implements ItemWriter<String> {
private final Resource resource;
public GSWriter(WritableResource resource) {
this.resource = resource;
}