The AWS SDK for Java v2 makes S3 access straightforward once you’ve seen the right shape for it. This post walks through a minimal Spring Boot configuration, the YAML settings that drive it, a small service with the S3 operations you’ll use most, and an integration test that runs against a real S3 API — without touching AWS — using Testcontainers and LocalStack.

Dependencies

xml

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.x.x</version>
</dependency>

application.yml

Keep credentials out of the YAML in real deployments — use environment variables, an instance profile, or a secrets manager. The block below shows the settings worth externalizing either way.

yaml

aws:
s3:
region: eu-central-1
bucket: my-app-bucket
endpoint: ${AWS_S3_ENDPOINT:} # only set for LocalStack/MinIO; blank for real AWS
path-style-access: false # true for LocalStack/MinIO

A matching @ConfigurationProperties class:

java

@ConfigurationProperties(prefix = "aws.s3")
public record S3Properties(
String region,
String bucket,
String endpoint,
boolean pathStyleAccess) {}

The S3Client bean

java

@Configuration
@EnableConfigurationProperties(S3Properties.class)
public class S3Config {
@Bean
public S3Client s3Client(S3Properties props) {
S3ClientBuilder builder = S3Client.builder()
.region(Region.of(props.region()))
.credentialsProvider(DefaultCredentialsProvider.create())
.serviceConfiguration(b -> b.pathStyleAccessEnabled(props.pathStyleAccess()));
if (props.endpoint() != null && !props.endpoint().isBlank()) {
builder.endpointOverride(URI.create(props.endpoint()));
}
return builder.build();
}
}

DefaultCredentialsProvider checks environment variables, system properties, the shared ~/.aws/credentials file, and the EC2/ECS instance role, in that order — so the same code works locally and in production without changes.

A minimal S3 service

java

@Service
public class S3StorageService {
private final S3Client s3Client;
private final String bucket;
public S3StorageService(S3Client s3Client, S3Properties props) {
this.s3Client = s3Client;
this.bucket = props.bucket();
}
public void upload(String key, byte[] content, String contentType) {
s3Client.putObject(
PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType(contentType)
.build(),
RequestBody.fromBytes(content));
}
public byte[] download(String key) {
return s3Client.getObject(
GetObjectRequest.builder().bucket(bucket).key(key).build(),
ResponseTransformer.toBytes()).asByteArray();
}
public List<String> listKeys(String prefix) {
return s3Client.listObjectsV2(
ListObjectsV2Request.builder()
.bucket(bucket)
.prefix(prefix)
.build())
.contents()
.stream()
.map(S3Object::key)
.toList();
}
public void delete(String key) {
s3Client.deleteObject(
DeleteObjectRequest.builder().bucket(bucket).key(key).build());
}
}

Four methods cover most day-to-day usage: putObject, getObject, listObjectsV2, and deleteObject. Everything else in the SDK is a variation on this same request/response builder pattern.

Hinterlasse einen Kommentar

I’m Iman

Mein Name ist Iman Dabbaghi. Ich arbeite als Senior Software Engineer in der Schweiz. Außerdem interessiere ich mich sehr für gewaltfreie Kommunikation, Bachata-Tanz und Musik sowie fürs die Persönlichkeitsentwicklung.

Ich habe einen Masterabschluss in Informatik von der Universität Freiburg in Deutschland, bin Spring/Java Certified Professional (OCP), Certified Professional for Software Architecture (CPSA-F) und ein lebenslanger Lernender 🎓.

EN:

My name is Iman Dabbaghi. I work as a Senior Software Engineer in Switzerland. I am also very interessted in nonviolent communication, Bachata dance and music and also for personal development.

I hold a masters degree in computer science from the university of Freiburg in Germany, am a Spring / Java Certified Professional (OCP), Certified Software Architecture (CPSA-F) and Life Long Learner🎓

Let’s connect