Eduardo Lopes
Eduardo Lopes

Reputation: 33

How to configure SQS endpoint via environment variable in Spring Boot?

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!

Upvotes: 2

Views: 634

Answers (1)

Geba
Geba

Reputation: 869

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

Upvotes: 1

Related Questions