How to read data from java properties file using Spring Boot - java

I have a spring boot application and I want to read some variable from my application.properties file. In fact below codes do that. But I think there is a good method for this alternative.
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
prop.load(input);
gMapReportUrl = prop.getProperty("gMapReportUrl");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
...
}

You can use #PropertySource to externalize your configuration to a properties file. There is number of way to do get properties:
1.
Assign the property values to fields by using #Value with PropertySourcesPlaceholderConfigurer to resolve ${} in #Value:
#Configuration
#PropertySource("file:config.properties")
public class ApplicationConfiguration {
#Value("${gMapReportUrl}")
private String gMapReportUrl;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
2.
Get the property values by using Environment:
#Configuration
#PropertySource("file:config.properties")
public class ApplicationConfiguration {
#Autowired
private Environment env;
public void foo() {
env.getProperty("gMapReportUrl");
}
}
Hope this can help

I have created following class
ConfigUtility.java
#Configuration
public class ConfigUtility {
#Autowired
private Environment env;
public String getProperty(String pPropertyKey) {
return env.getProperty(pPropertyKey);
}
}
and called as follow to get application.properties value
myclass.java
#Autowired
private ConfigUtility configUtil;
public AppResponse getDetails() {
AppResponse response = new AppResponse();
String email = configUtil.getProperty("emailid");
return response;
}
application.properties
emailid=sunny#domain.com
unit tested, working as expected...

i would suggest the following way:
#PropertySource(ignoreResourceNotFound = true, value = "classpath:otherprops.properties")
#Controller
public class ClassA {
#Value("${myName}")
private String name;
#RequestMapping(value = "/xyz")
#ResponseBody
public void getName(){
System.out.println(name);
}
}
Here your new properties file name is "otherprops.properties" and the property name is "myName". This is the simplest implementation to access properties file in spring boot version 1.5.8.

Related

Is it necessary to use Commons Configuration to use #PropertySource in Spring 5.x?

I am unable to load property file in resources directory,
#Configuration
#PropertySource(value = "classpath:/test.properties", ignoreResourceNotFound = true)
public class ArgConfig {
#Autowired
private Environment env;
#Value("${store.name}")
private String name;
public String getName() {
return name;
}
}
test.properties contains -->
store.name=nike
Property Source from Spring Documentation
Followed the same from the documentation still unable to load the properties file.
Is it mandatory for you to use it as test.properties? if so, use the #PropertySource annotation. Otherwise, use it like application-test.properties and set the profile as test using #ActiveProfiles("test")
Another way is, place your application.properties under src/test/resources if you want to override the value.
Refer https://www.baeldung.com/spring-tests-override-properties for more information
Apologies for wasting precious time.
I found the answer, it is just to place the property file under resource directory(which I did even before but not sure why it thrown error).
Here is the entire code,
Project structure:
#RestController
#RequestMapping("/")
public class SampleRestController {
#Autowired
private Store storeDetails;
#GetMapping("/names")
public List<String> getNames(){
String storeName = storeDetails.getName();
System.out.println("Store Name = " + storeName);
return storeName!=null ? Arrays.asList(storeName) : Arrays.asList("store1","store2","store3");
}
}
#Configuration
#PropertySource("classpath:/store.properties")
public class StoreConfig {
#Autowired
Environment env;
#Bean
public Store storeDetails() {
Store store = new Store();
store.setName(env.getProperty("store.name"));
return store;
}
}
#Component
public class Store {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class);
}
}
Thanks everyone!!!

Parameter 0 of constructor required a bean of type 'FileStoragePropertiesAedImages'

I have been on stack in several threads regarding this question although I still can not figure it out.
Parameter 0 of constructor in com.aed.demo.fileupload.FileStorageServiceAedImages required a bean of type 'com.aed.demo.fileupload.FileStoragePropertiesAedImages' that could not be found.
Action:
Consider defining a bean of type 'com.aed.demo.fileupload.FileStoragePropertiesAedImages' in your configuration.
I have created a FileStorageService and a FileStorageProperties files
File Storage Properties
#ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
}
File Storage Service
#Service
public class FileStorageService {
private final Path fileStorageLocation;
#Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
...
}
the above set up works like a charm and creates the directory file.upload-dir=home/.. that it's defined in the application.properties
I tried duplicating these two configurations with another file upload directory in application.properties
Second FileStorageProperties Class
#ConfigurationProperties(prefix = "aed")
public class FileStoragePropertiesAedImages {
private String uploadDir;
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
}
Second FileStorageService
#Service
public class FileStorageServiceAedImages {
private final Path fileStorageLocation;
#Autowired
public FileStorageServiceAedImages(FileStoragePropertiesAedImages fileStoragePropertiesAED) {
this.fileStorageLocation = Paths.get(fileStoragePropertiesAED.getUploadDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
...
}
and then the above error is thrown. I need to create 3 directories that I've defined like so in application.properties
file.upload-dir=home/..
mobile.upload-dir=mobile/..
aed.upload-dir=aed/..
prefixes are correct, why the second storage service can not be initialized and requires a bean type and the first one does not?
what you are doing is constructor autowiring at FileStorageServiceAedImages which requires bean of type FileStoragePropertiesAedImages but you have not defined bean of the type. You just added # ConfigurationProperties to the FileStorageProperties. Adding #Configuration to FileStorageProperties will create the bean you required at FileStoragePropertiesAedImages.
Add #Configuation annotation to FileStoragePropertiesAedImages class should solve the problem.
#ConfigurationProperties(prefix = "aed")
#Configuation
public class FileStoragePropertiesAedImages {

Spring read property file outside the class path

I have a property file located in tomcat folder.Im trying to read the propert file content as follow.but im getting null value for the property value.
file path has no any issue.
#ComponentScan(basePackages = "org.sakaiproject.log.api")
#Configuration
#PropertySource(name = "props", value = {
"file:/home/tomcat-sakai-7.0.55/sakai/local.properties",
"file:/home/tomcat-sakai-7.0.55/sakai/sakai.properties" })
public class SpringCryptoContext {
#Value("${aes.encryption.cipherString}")
private static String cyperString;
public SpringCryptoContext() {
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(
SpringCryptoContext.class);
System.out.println(cyperString);
}
}
Edit:
I created seperate class and load the properties as follow.
#Service
#PropertySource(name = "locations", value = {
"file:/home/nirmala/projects/iml/tomcat-sakai-7.0.55/sakai/local.properties",
"file:/home/nirmala/projects/iml/tomcat-sakai-7.0.55/sakai/sakai.properties" })
public class CryptoToolImpl implements CryptoTool {
private Cipher cipher = null;
private Key key = null;
#Value("${pii.encryption.cipherString}")
private String cipherString = "";
public static final Logger log = Logger.getLogger(CryptoToolImpl.class);
public IMLCryptoToolImpl() {
try {
fixKeyLength();
cipher = Cipher.getInstance(cipherString);
key = KMSKeyStoreSingleton.getInstance().getPrivateKey();
} catch (Exception e) {
log.error("Error in initializing CryptoToolImpl : "
+ e.getMessage());
}
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
but i get the following error
Error in initializing CryptoToolImpl : Invalid transformation format:
Please add the following bean in your configuration class:-
//To resolve values using the #Value
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigDev() {
return new PropertySourcesPlaceholderConfigurer();
}
Update
static won't work in this case, you need to do the following:-
Add the following code:-
#Value("${aes.encryption.cipherString}")
private String cyperString;
public String getCypherString(){
return this.cyperString;
}
This is just an example, but static you are using because you are accessing it in the main method which is static and for accessing the variable, you marked it static
The issue is that the static variable is a class variable which is having no property when the code reaches at your line of System.out for the variable, At this time - spring is still doing internal initialization etc..
You are accessing/ using the variable as non spring framework while you are instantiating using spring. It has to be single way only
And I would suggest to have a separate class to load these variables into context, may be some class marked with #Component or more specifically #Service
Something below should help.
#Configuration
#PropertySources(value={
#PropertySource(value="file:${catalina.home}/sakai/local.properties"),
#PropertySource(value="file:${catalina.home}/sakai/sakai.properties")
})
public class SpringCryptoContext {
#Value("${aes.encryption.cipherString}")
private String cyperString;
}

IllegalArgumentException: Invalid boolean value when injecting property to boolean in Spring

In Spring Boot I attempt to inject a boolean value to an instance variable from an enviroment property which is set (enabled=true).
#Value("${enabled}")
private boolean enabled;
However Spring cannot resolve this for some reason and reports:
Caused by: java.lang.IllegalArgumentException: Invalid boolean value [${enabled}]
It seems like it does not replace expression ${enabled} with the property value.
What needs to be set ? Why doesn't work this by default ?
For Spring-Boot you can find good reference here:
http://www.baeldung.com/properties-with-spring
For given someprops.properites file:
somevalue:true
Here is FAILING version:
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#TestPropertySource( "/someprops.properties" )
public class FailingNg {
#Configuration
public static class Config {
}
#Value("${somevalue}")
private Boolean somevalue;
// Fails with context initializatoin java.lang.IllegalArgumentException: Invalid boolean value [${somevalue}]
#Test
public void test1() {
System.out.println("somevalue: " + somevalue);
}
}
Here is WORKING version:
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class WorkingOk {
#Configuration
public static class Config {
#Bean
public static PropertyPlaceholderConfigurer properties() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[] {
new ClassPathResource( "someprops.properties" )
};
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
return ppc;
}
}
#Value("${somevalue}")
private Boolean somevalue;
#Test
public void test1() {
System.out.println("somevalue: " + somevalue);
}
}
As mentioned in the comments, you are likely missing a PropertySourcesPlaceholderConfigurer bean definition. Here's an example of how to configure that within Java:
#Configuration
public class PropertyConfig {
private static final String PROPERTY_FILENAME = "app.properties"; // Change as needed.
/**
* This instance is necessary for Spring to load up the property file and allow access to
* it through the #Value(${propertyName}) annotation. Also note that this bean must be static
* in order to work properly with current Spring behavior.
*/
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[] { new ClassPathResource(PROPERTY_FILENAME) };
pspc.setLocations(resources);
pspc.setIgnoreUnresolvablePlaceholders(true);
return pspc;
}
}

classpath wildcard in #PropertySource

I am using Spring Java config to create my bean.
But this bean is common to 2 applications.
Both have one property file abc.properties but with different classpath locations.
When i put explicit classpath like
#PropertySource("classpath:/app1/abc.properties")
then it works but when i try to use wildcard like
#PropertySource("classpath:/**/abc.properties")
then it doesn't work.
I try many combinations of wildcard but it still not working.
Is wildcard works in #ProeprtySource
Is there any other way to read to property in classed marked with #Configurations.
#PropertySource API: Resource location wildcards (e.g. **/*.properties) are not permitted; each location must evaluate to exactly one .properties resource.
workaround: try
#Configuration
public class Test {
#Bean
public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer()
throws IOException {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/**/abc.properties"));
return ppc;
}
Addidtionally to dmay workaround:
Since Spring 3.1 PropertySourcesPlaceholderConfigurer should be used preferentially over PropertyPlaceholderConfigurer and the bean should be static.
#Configuration
public class PropertiesConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
PropertySourcesPlaceholderConfigurer propertyConfigurer = new PropertySourcesPlaceholderConfigurer();
propertyConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/**/abc.properties"));
return propertyConfigurer;
}
}
If you're using YAML properties, this can be achieved using a custom PropertySourceFactory:
public class YamlPropertySourceFactory implements PropertySourceFactory {
private static final Logger logger = LoggerFactory.getLogger(YamlPropertySourceFactory.class);
#Override
#NonNull
public PropertySource<?> createPropertySource(
#Nullable String name,
#NonNull EncodedResource encodedResource
) {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
String path = ((ClassPathResource) encodedResource.getResource()).getPath();
String filename = encodedResource.getResource().getFilename();
Properties properties;
try {
factory.setResources(
new PathMatchingResourcePatternResolver().getResources(path)
);
properties = Optional.ofNullable(factory.getObject()).orElseGet(Properties::new);
return new PropertiesPropertySource(filename, properties);
} catch (Exception e) {
logger.error("Properties not configured correctly for {}", path, e);
return new PropertiesPropertySource(filename, new Properties());
}
}
}
Usage:
#PropertySource(value = "classpath:**/props.yaml", factory = YamlPropertySourceFactory.class)
#SpringBootApplication
public class MyApplication {
// ...
}

Categories

Resources