Spring-boot parameterizing - java

I am new to Spring-bot and I need to add a configuration file inside the resources folder and read values from it.
Right now what I have done is that I have created a 'Configuration.properties' file in the classpath folder and have invoked the properties inside the program
FileReader reader=new FileReader("Configuration.properties");
Properties p=new Properties();
p.load(reader);
return p;
Can somebody please help how can i make it to call from the application.properties file of the spring-boot(or similar files) and thus make my configurations available inside the jar which I create.
PS: The Configurations i have given is project specific and am using them for avoiding the hardcoding inside the code.

Create application.properties file in the resource folder, spring boot will automatically find it.
Say you use these properties
test.stringProperty=will_be_used
test.integerProperty=42
stringProperty=not_used
You can then create a configuration properties class like so
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties(prefix = "test")
public static class TestProperties {
private String stringProperty;
private Integer integerProperty;
// getters and setters
}
and use it
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
#Configuration
#EnableConfigurationProperties(TestProperties.class)
public class TestConfiguration {
#Autowired
private TestProperties config;
// do whatever with properties
}
The autowired object will then have the values you specified in application.propertiesfile with the name 'prefix'.'name of the variable'.
Or you can use the
#Value("${stringProperty}")
private String value;
which is easier at first, but not very maintainable for higher number of properties.

You can use the #Value annotation to get the property file values.
Ex :
#Value("${rest_api_url}")
private String restApiUrl;

Need to define Property file as per requirement of your app.
You can use the #Value annotation in bean.
refer : Externalized Configuration and Properties and Configuration

Create a file in resource folder by the name application.properties which will be taken automatically as the default property file.
If you want to specify some other file as a property, do the below-mentioned changes.
Snippet :
#SpringBootApplication
#ImportResource("classpath:filename.properties")
public class Example{
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}

Related

Spring Boot - inject map from properties file [duplicate]

This question already has answers here:
How to fill HashMap from java property file with Spring #Value
(8 answers)
Closed 2 years ago.
property file looks like this:
url1=path_to_binary1
url2=path_to_binary2
According this I tried following approach:
#Component
#EnableConfigurationProperties
public class ApplicationProperties {
private Map<String, String> pathMapper;
//get and set
}
and in another component I autowired ApplicationProperties:
#Autowired
private ApplicationProperties properties;
//inside some method:
properties.getPathMapper().get(appName);
produces NullPointerException.
How to correct it?
update
I have correct according user7757360 advice:
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix="app")
public class ApplicationProperties {
and properties file:
app.url1=path_to_binary1
app.url2=path_to_binary2
Still doesn't work
Update 2
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix="app")
public class ApplicationProperties {
private Map<String, String> app;
and inside application.properties:
app.url1=path_to_binary1
app.url2=path_to_binary2
Still doesn't work
it would be helpful if you can give a more specific example for property file. You should have the same prefix in the url1 and url2 and then you can use
#ConfigurationProperties(prefix="my")
as in
my.pathMapper.url1=path_to_binary1
my.pathMapper.url2=path_to_binary2
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix="my")
public class ApplicationProperties {
private Map<String, String> pathMapper;
//get and set for pathMapper are important
}
see more at https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-loading-yaml
NullPointerException is probably from empty ApplicationProperties.
All custom properties should be annotated #ConfigurationProperties(prefix="custom").
After that, on your main class (class with main method) you must add #EnableConfigurationProperties(CustomProperties.class).
For autocomplete you can use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
If you use #ConfigurationProperties without prefix you use only field name. Field name in you properites. In your case path-mapper, next you specific key and value. Example:
path-mapper.key=value
Remeber after changes in your own properites you need to reload application. Example:
https://github.com/kchrusciel/SpringPropertiesExample
There are two things need you need to feed map from properties file. First you need to have a class which has the configuration and target fields to hold data from properties file.
#Configuration
#PropertySource("classpath:myprops.properties")
#ConfigurationProperties("props")
#Component
public class Properties{
private Map<String,String> map = new HashMap<String,String>();
// getter setter
}
Secondly define the properties file named myprops.properties with all properties as props
props.map.port = 443
props.map.active = true
props.map.user = aUser
Have the your.properties file under src/main/resources and either have it as a
#Configuration
#PropertySource("classpath:your.properties")
public class SpringConfig(){}
or have it as a PropertyPlaceholderConfigurer in your Spring yourApplicationContext.xml.
Then use the property values like
#Value("app.url1")
String path_to_binary1;
#Value("app.url2")
String path_to_binary2;
// ...
System.out.println(path_to_binary1+path_to_binary2);

Getting properties object in spring

I have a properties file called xyz.properties. Right now, I am able to load individual property of this file in my class annotated with #Component which is working perfectly fine.
However, I am thinking of making my project more modular, for which I need to read the whole xyz.properties file as one properties object so that i can pass it along. How can I do so ?
Update
Right now, I am loading individual property from the file like this
my applicationContext.xml has following entry
<context:property-placeholder location="classpath:xyz.properties" order="2" ignore-unresolvable="true"/>
and then i have the respective class as
#Component
public class XyzConfiguration {
#Value("${client.id}")
private String clientId;
#Value("${client.secret}")
private String clientSecret;
...
}
What I mean by pass it along
Right now, for each individual property I have to create a respective field in a class and then annotate it with respective property name. By doing so, I am making my nested module very spring framework specific. I might someday put this module on github for others as well and they may or may not use spring framework. For them it would be easier to create an object of this module by passing required parameters (ideally in case of a Properties object) so that my module will fetch the properties by itself.
You can try below code.
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.io.ResourceLoader;
import java.util.Properties;
private String fileLocator;
private Properties prop;
private ResourceLoader resourceLoader;
public void init() throws IOException {
//"fileLocator" must be set as a path of file.
final Resource resource = resourceLoader.getResource(fileLocator);
prop = PropertiesLoaderUtils.loadProperties(resource);
}
prop will have all values from your property file and then you can get any value by calling prop.getProperty() method.

Loading multiple YAML files (using #ConfigurationProperties?)

Using Spring Boot 1.3.0.RELEASE
I have a couple of yaml files that describe several instances of a program. I now want to parse all those files into a List<Program> (Map, whatever), so I can later on search for the most appropriate instance for a given criteria in all the programs.
I like the approach with #ConfigurationProperties a lot, and it works good enough for a single yaml-file, but I haven't found a way yet to read all files in a directory using that method.
Current approach working for a single file:
programs/program1.yml
name: Program 1
minDays: 4
maxDays: 6
can be read by
#Configuration
#ConfigurationProperties(locations = "classpath:programs/program1.yml", ignoreUnknownFields = false)
public class ProgramProperties {
private Program test; //Program is a POJO with all the fields in the yml.
//getters+setters
I tried changing the locations to an Array listing all of my files locations = {"classpath:programs/program1.yml", "classpath:programs/program2.yml"} as well as using locations = "classpath:programs/*.yml", but that still only loads the first file (array-approach) or nothing at all (wildcard-approach).
So, my question is, what is the best way in Spring Boot to load a bunch of yaml files in a classpath-directory and parse them into a (List of) POJO, so they can be autowired in a Controller? Do I need to use Snakeyaml directly, or is there an integrated mechanism that I just haven't found yet?
EDIT:
A working approach is doing it manually:
private static final Yaml yaml = new Yaml(new Constructor(Program.class));
private static final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
for (Resource resource : resolver.getResources("/programs/*.yml")) {
Object data = yaml.load(resource.getInputStream());
programList.add((Program) data);
}
}
catch (IOException ioe) {
logger.error("failed to load resource", ioe);
}
In Spring, it is possible to load multiple configuration properties files using PropertySource annotation, but not YAML files. See section 26.6.4 in link below:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties
However, from your problem, it seems that you can configure all your programs in single YAML and then get all list of programs in a single list.
Sample YAML (all.yaml)
programs:
- name: A
min: 1
max: 2
- name: B
min: 3
max: 4
Config.java
#Configuration
#ConfigurationProperties(locations={"classpath:all.yaml"})
public class Config{
private List<Program> programs;
public void setPrograms(List<Program> programs) {
this.programs = programs;
}
public List<Program> getPrograms() {
return programs;
}
}
What I am currently doing, as far as I understood your question, is nearly the same.
I am having an application.yml and also profile-specific yml files, e.g. application-{profile}.yml in my src/main/resources.
In the application.yml I have defined the default profile key-values, which are partially overridden by the profile-specific yml files.
If you want to have a type-safe and well defined access of your YML key/values, then you can use the following approach:
#ConfigurationProperties
public class AppSettings {
String name; // has to be the same as the key in your yml file
// setters/getters
}
In your Spring-Boot config, you have to add the following annotations onto your config class:
#ComponentScan
#EnableAutoConfiguration
#EnableConfigurationProperties( value = { AppSettings.class, SomeOtherSettings.class } )
public class SpringContextConfig {
#Autowired
private AppSettings appSettings;
public void test() {
System.out.println(appSettings.getName());
}
}
The #Autowiring is also accessible from other Beans.
The other way around (without an extra separated and type-safe class, is to access the YML-values via #Value("${name}").
To bring it together in a short manner:
Yes, it is possible to use several YAML files for your application via Spring-profiles. You define your current active spring profile via command args, programmatically or via your system env (SPRING_PROFILES_ACTIVE=name1,name2).
Therefore you can have several application.yml files for each profile (see above).

#Value annotation not resolved in a class that belongs to dependency jar

I have a simple web-app that includes a dependency jar for some functionality and needs to use a property value defined in main app code.
Thanks in advance to help me out on this.
dependency.jar contains
public class MyClass {
#Value("${abc.def}")
private String abc; // DOES NOT GET RESOLVED. IS ALWAYS NULL
}
dependency-context.xml
my-app.war contains
public class LocalClass {
#Value("${abc.def}")
private String abc; // GETS RESOLVED TO CORRECT PROPERTY VALUE
}
context.xml
imports dependency-context.xml
You may be running into this bug. It makes it very difficult to use the #Value with multiple PropertyPlaceholderConfigurers from different projects using import context. To solve this problem try to autowire the existing PropertyPlaceholderConfigurer into your bean configuration method (assuming you can use #Configuration) and update the object in the method with the values from your project.
#scottmf is on the right lines, but you can't read properties directly from PropertyPlaceholderConfigurer :(
Instead, I created a String #Bean in the war...
<bean id="myProperty" class="java.lang.String">
<constructor-arg value="ABC"/>
</bean>
which can be #Autowired into the jar class:
#Bean
public Object myBean(String myProperty) { ... }

How Or where Do I access my properties file

I have a properties file myprops.properties as follows:
Wsdl=someurl
UserName=user
UserPassword=pasword
Application=appName
And inside my controller I'm trying to access to set values in my service as follows
Properties prop = new Properties();
prop.load(new FileInputStream("resources/myprops.properties"));
myService.setWsdl(prop.getProperty("Wsdl"));
myService.setUserName(prop.getProperty("UserName"));
myService.setUserPassword(prop.getProperty("UserPassword"));
myService.setApplication(prop.getProperty("Application"));
my Issue is I just do not know what path to use. Its a Spring project if that makes any difference. and Idealy I would like to have the properties file in my "src/main/resources" folder
I realise this may be very simple to some but I have tried searching for the solution both here and on Google and I cannot seem to find a solution that has helped. I've tried moving the file around the project but cannot seem to figure it out
The Error I get is
java.io.FileNotFoundException: resources\drm.properties (The system cannot find the path specified)
any advice/explanation or even a link that clearly explains it would be great
well, src/main/resources are on the classpath, you just need to do.
Properties properties = PropertiesLoaderUtils.loadAllProperties("your properties file name");
If you are using spring, you could set your property placeholder.
<context:property-placeholder location="classpath:resources/myprops.properties" />
and in your beans you can inject the values from the properteis using the #Value annotation
#Autowired
public Foo(#Value("${Wsdl}") String wsdl) {
...
}
in the case above I used in the constructor, but its possible to use by Autowired field/setter.
So in your service you could have something like:
#Service
public class MyService {
private final String wsdl;
private final String username;
private final String password;
private final String application;
#Autowired
public MyService(
#Value("${Wsdl}") String wsdl,
#Value("${UserName}") String username,
#Value("${UserPassword}") String password,
#Value("${Application}") String application
) {
// set it to each field.
}
}
Given that src/main/resources is on the classpath, you could do:
Resource resource = new ClassPathResource("/myprops.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
Don't use a FileInputStream; use getResourceAsStream() to read it from the servlet context.
You can always count on mkyong. This is an example/tutorial on how to load and read property files.
http://www.mkyong.com/java/java-properties-file-examples/
This question should be marked as a duplicate:
Loading a properties file from Java package
How to use Java property files?
Load a property file in Java
Java Properties File not loading
Java NullPointerException on loading properties file
Not able to load properties file in Java

Categories

Resources