I have a Spring boot application that requires the use of properties in files different from the standard application.properties. I wanted to map my properties files to a specific properties class and be able to use the properties class inside of a Configuration class. The code is the following:
@Configuration
@EnableConfigurationProperties(AWSProperties.class)
@PropertySource("kaizen-batch-common-aws.properties")
public class ResourceConfigAWS {
@Autowired
private AWSProperties awsProperties;
@Autowired
private ResourceLoader resourceLoader;
private static final Logger logger = LoggerFactory.getLogger(ResourceConfigAWS.class);
@Bean
public AmazonS3 amazonS3Client() {
logger.debug("AWS Config: " + this.awsProperties);
BasicAWSCredentials awsCreds = new BasicAWSCredentials("access_key_id", "secret_key_id");
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(awsProperties.getRegion())
.build();
return s3Client;
}
@Bean
public SimpleStorageResourceLoader resourceLoader() {
return new SimpleStorageResourceLoader(this.amazonS3Client());
}
@Bean
@StepScope
public Resource getResourceToProcess(@Value("#{jobParameters[T(com.kaizen.batch.common.JobRunnerTemplate).INPUT_FILE_PARAM_NAME]}") String inputFile) {
return this.resourceLoader.getResource(this.awsProperties.getInputLocation() + inputFile);
}
@PostConstruct
public void postConstruct() {
System.out.print("Properties values: " + this.awsProperties);
}
@Bean
public AbstractFileValidator inputFileValidator() {
InputS3Validator inputS3Validator = new InputS3Validator();
inputS3Validator.setRequiredKeys(new String[]{InputFileSystemValidator.INPUT_FILE});
return inputS3Validator;
}
@Bean
public InputFileFinalizerDelegate inputFileFinalizerDelegate() {
InputFileFinalizerDelegate inputFileFinalizerDelegate = new AWSInputFileFinalizerDelegate();
return inputFileFinalizerDelegate;
}
@Bean
public InputFileInitializerDelegate inputFileInitializerDelegate() {
InputFileInitializerDelegate inputFileInitializerDelegate = new AWSInputFileInitializerDelegate();
return inputFileInitializerDelegate;
}
}
@ConfigurationProperties("aws")
@Data
public class AWSProperties {
private static final String SEPARATOR = "/";
private static final String S3_PREFFIX = "s3://";
@Value("${s3.bucket.batch}")
private String bucket;
@Value("${s3.bucket.batch.batch-job-folder}")
private String rootFolder;
@Value("${s3.bucket.batch.input}")
private String inputFolder;
@Value("${s3.bucket.batch.processed}")
private String processedFolder;
@Value("${region}")
private String region;
public String getInputLocation() {
return this.getBasePath() + this.inputFolder + SEPARATOR;
}
public String getProcessedLocation() {
return this.getBasePath() + this.processedFolder + SEPARATOR;
}
private String getBasePath() {
return S3_PREFFIX + this.bucket + SEPARATOR + this.rootFolder + SEPARATOR;
}
}
I am struggling to manage to Get AWSProperties to get populated with the values defined in the properties files, somehow I always end up with awsProperties with a null value. Any insight on how to map properties in Spring Boot into a Properties class without using the standard property files naming conventions in Spring Boot will be very appreciated.
Here is the properties file:
aws.s3.bucket.batch=com-kaizen-batch-dev
aws.s3.bucket.batch.input=input
aws.s3.bucket.batch.processed=processed
aws.s3.bucket.batch.batch-job-folder=merchant-file
aws.region=us-east-2
Note: I modified the Configuration class slightly and now I am getting the following exception:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.kaizen.batch.common.ResourceConfigAWS': Unsatisfied dependency expressed through field 'awsProperties'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aws-com.kaizen.batch.common.AWSProperties': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 's3.bucket.batch' in value "${s3.bucket.batch}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
@ConfigurationProperties
are used for binding property file keys with POJO classes. You have to do following changes for your code to work.
kaizen-batch-common-aws.properties
aws.s3.bucket.batch.bucket=com-kaizen-batch-dev
aws.s3.bucket.batch.root-folder=processed
aws.s3.bucket.batch.input-folder=input
aws.s3.bucket.batch.processed-folder=processed
aws.s3.bucket.batch.batch-job-folder=merchant-file
@Component
@ConfigurationProperties(prefix = "aws.s3.bucket.batch")
public class AWSProperties {
private String bucket;
private String rootFolder;
private String inputFolder;
private String processedFolder;
private String region;
// setter require
}
Please visit doc here