I have a Spring Boot project that uses SQS queues. For local testing, I’m using a Docker container with LocalStack. To make the connection between my project and LocalStack work, the only way I found is by overriding the SQS endpoint directly in the configuration class, as shown below:
@Configuration
public class SQSClientConfig {
@Bean
public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
return SqsMessageListenerContainerFactory
.builder()
.sqsAsyncClient(sqsAsyncClient())
.build();
}
@Bean
public SqsAsyncClient sqsAsyncClient() {
var credentials = EnvironmentVariableCredentialsProvider.create();
return SqsAsyncClient.builder()
.credentialsProvider(credentials)
.endpointOverride(URI.create("http://localhost:4566")) *HERE*
.region(DefaultAwsRegionProviderChain.builder()
.build().getRegion())
.build();
}
@Bean
public Listener listener() {
return new Listener();
}
}
However, since my project also runs in a container on AWS, I don’t want to remove this line every time I deploy it in AWS. Is there a way to override the SQS endpoint using environment variables instead? I have tried many environment variables and config properties, but the connection always falls back to the default URL (sqs.us-east-2.amazonaws.com).
Any suggestions on how to solve this would be greatly appreciated!
I would suggest the following approach:
In your config file, e.g. application.yml
, define the following key-value pair
sqs_endpoint: ${SQS_ENDPOINT:}
In the file from your example, change definition of SqsAsyncClient
to the following:
@Bean
public SqsAsyncClient sqsAsyncClient(@Value("${sqs_endpoint}") String sqsEndpoint) {
var credentials = EnvironmentVariableCredentialsProvider.create();
var builder = SqsAsyncClient.builder();
var isSqsEndpointPassed = sqsEndpoint != null && !sqsEndpoint.trim().isEmpty();
if (isSqsEndpointPassed) {
builder.endpointOverride(URI.create(sqsEndpoint))
}
return builder
.credentialsProvider(credentials)
.region(DefaultAwsRegionProviderChain.builder()
.build().getRegion())
.build();
}
When you run your application locally pass environment variable
java -jar app.jar -DSQS_ENDPOINT=http://localhost:4566
Another common approach is to have 2 active profiles - default and local.
Define the default configurations in application.yml
and the local configurations in application-local.yml
.
And when you run your application locally, pass the active profile using the following key -Dspring.profiles.active=local