Issue
I am trying to build a springboot application integrated with S3 and SQS. I have an AppConfig, S3Config, SqsConfig wherein I autowire the S3Config and SqsConfig inside the AppConfig.
S3Config declares a bean s3client which I use to perform aws s3 operations. I am getting an error where in the autowiring is failing due to multiple bean definitions available but I'm not sure what part is causing what duplicacy. Attaching the snippets.
Note that I am creating a different definition of s3client bean depending on the profile ( local development vs server deployment )
AppConfig
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@Slf4j
@Component
@RefreshScope
@Getter
public class AppConfig {
@Autowired
S3Config s3Config;
@Autowired
SqsConfig sqsConfig;
}
S3Config
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Configuration
@Slf4j
@Component
@RefreshScope
@Getter
public class S3Config {
@Value("${aws.s3.roleArn}")
private String s3RoleArn;
@Value("${aws.s3.roleSessionName}")
private String s3RoleSessionName;
@Value("${aws.s3.region}")
private String s3region;
@Value("${aws.s3.inputBucketName}")
private String inputBucketName;
@Value("${aws.s3.outputBucketName}")
private String outputBucketName;
@Bean(name = "s3client")
@Profile("!local")
public AmazonS3 AmazonS3Client() {
log.info(String.format("validating_config_repo_values: s3RoleArn=%s s3RoleSessionName=%s s3RoleSessionName=%s", s3RoleArn, s3RoleSessionName,s3region));
AmazonS3 s3client = null;
try {
STSAssumeRoleSessionCredentialsProvider roleCredentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(
s3RoleArn, s3RoleSessionName).build();
AmazonS3ClientBuilder amazonS3ClientBuilder = AmazonS3ClientBuilder.standard()
.withCredentials(roleCredentialsProvider);
s3client = amazonS3ClientBuilder.withRegion(s3region).build();
} catch (Exception e) {
log.error(String.format("exception_while_creating_AmazonS3Client : %s", e));
}
return s3client;
}
@Bean(name = "s3client")
@Profile("local")
public AmazonS3 localhostAmazonS3Client() {
AmazonS3 s3client = null;
try {
s3client = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).withCredentials(new DefaultAWSCredentialsProviderChain()).build();
} catch (Exception e) {
log.error(String.format("exception_while_creating_AmazonS3Client : %s", e));
}
return s3client;
}
}
UploadServiceImpl
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@Service
@Slf4j
public class S3DatasetDownloadServiceImpl implements DatasetDownloadService {
@Autowired
AmazonS3 s3Client;
@Autowired
AppConfig appConfig;
public String downloadDataset(URI uri) throws IOException {
String key = uri.getPath();
String outputBucketName = appConfig.getS3Config().getOutputBucketName();
log.info(String.format("client_downloading_file : key=%s from bucket=%s",key,outputBucketName));
try {
} catch (Exception e) {
}
}
}
Solution
Kill me. Found the error, I have the bean name as s3client
( c of client small ) whereas on autowiring I am using AmazonS3 s3Client;
Fixing the casing worked!
Answered By - Kshitij Kohli
Answer Checked By - David Goodson (JavaFixing Volunteer)