I have a "details.yml" file, considering all the setting for getting all values from "yml.file" is done. But I am unable to store Map values into
"Map"
Here is my "details.yml" file below
details:
company:XYZ
values:
name: Manish
last: Raut
And in my class file i am able to get the values of "company" from yml file using #Value("${company}")
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "details")
public class abcd() {
#Value("${company}")
String company;
#Value("${values}")
Map<String, String> values =new HashMap<String, String>();
...............................
}
i am not able to get those values in Mao which i created in this class, but i am getting values for "Company".
Help me with this?
Im the past, I added getter/setter for MAP type and it was work.
Did you try it? (getter/setter for 'values')
I'm not really sure what marshalling framework Spring uses behind the scenes and how it configures it (you could probably find out with some debugging and maybe make it work for your case), but you could always add an extra layer to your application and configure your own.
For instance you could use Jackson with yaml dataformat - https://dzone.com/articles/read-yaml-in-java-with-jackson.
Related
I have a property that looks like:
#Value(...)
Map<String, List<String>> classToMethods;
I want to populate this map via my application.yml in a Spring Boot application via the #Value("...") annotation. Some sample values are:
"java.lang.Double" => ["parseDouble", "toString"]
"java.lang.String" => ["toUpperCase"]
How do I represent this in my application.yml file? Also, I would like to put placeholder for environmentally injected values from our deployment tool. So for example, I currently have:
some:
property: ${ENV_VALUE:default_value_if_no_env}
Basically, this is the syntax I use for injecting values for the specific environment(value for ENV_VALUE varies for each environment). I am looking for a way to format the YML map such that this kind of environment replacements are also possible.
Alternative I am thinking of is just creating a String and manually parsing it during constructor injection but would like to avoid if possible.
I have a yaml file which consist of placeholders to be taken from environment variable. I want to parse it to a custom class. Currently I am using snakeyaml library to parse it and its populating the bean correctly, how can I resolve environment variables using snakeyaml or any other library in Java.
datasource:
url: {url_environment_variable}
foo: bar
username: {user_name_environment_variable}
password: {password_environment_variable}
#Getter
#Setter
public class DataSource {
private String url;
private String foo;
private String username;
private String password;
}
Parsing code below
Constructor c = new Constructor(MyDataSource.class);
Yaml yaml = new Yaml(c);
MyDataSource myData = yaml.loadAs(inputStream, MyDataSource.class);
The problem is I am yet to find a way to resolve placeholders. People were able to solve it using python and is available in question -
How to replace environment variable value in yaml file to be parsed using python script
How can I do the same in Java. I can add a new dependency if required.
PS - It's not a Spring Boot Project so standard Spring placeholder replacements can not be used.
The easiest way would be to do it in two passes. First deserialize into MyDataSource as you’re doing already. Then use reflection to iterate over all fields of the instance, and if the value starts with a curly brace and ends with one, extract the key, and get the value from System.getenv map. See this answer for code.
If you want to do it in one pass, then you need to use the snakeyaml event-driver parser. For every key, you resolve the value as described above, and then based on the key name, set the corresponding field in the MyDataSource class, either using reflection, or simple if-else. For an example of the event-driven parser, see this class; it’s not Java, it’s Kotlin, but it may be the only JVM language example you’ll find.
I'm creating a microservice with Spring Boot that uses some properties loaded both with #Value and #ConfigurationProperties. Those properties will have default values defined in the application.yaml but I want to override them with environment variables. I've manage to do it with almost every basic property type but I'm unable with maps.
This is the code that retrieves the property, so the map is found in configuration.map:
#Data
#ConfigurationProperties(prefix = "configuration")
public class MapConfig{
private Map<String, Object> map;
}
The default values I have in the application.yaml are:
configuration:
map:
a: "A"
b: 2
c: true
This works fine and I get a map containing those key-value entries. Problem comes when I try to initialize the map with the environment variables. I've tried with multiples variants of CONFIGURATION_MAP='{aa:"aa", bb:12, cc:true}' and every time I start the application I get the default values defined in application.yaml but no trace of the environment map.
I also tried adding variables like CONFIGURATION_MAP_AA='HELLO' and I was able to put new values in my map. However all I can do is adding information but the default values I wrote in the yaml are still there. In this case I'm getting:
{
"aa": "HELLO",
"a": "A",
"b": 2,
"c": true
}
This isn't the behavior I'm looking for. I want to completely override the default map instead of adding new info. It also has the problem that keys added this way are always transformed to lowercase so I can't override keys with camelCase. And values are also casted to strings even when my map is <String,Object>.
Can anyone tell me how to properly initialize maps with environment variables or point me in the right direction? Thanks a lot!
The problem is the order in which the properties are been loaded.
Have a look at this doc that explains the loading order. I don't know if it will be
useful for your scenario but you can try creating a profile (for example application-other.yml) and load this. It will load after the application.yml
The cast is coming from the most general type in your list. In the end all three "name, 1, true" can be Strings. I can't think of a way of loading Object but you can recast your String on what you like ( if its needed. ) Else break it into multiple maps that are type specific ( Map<String,String> , Map<String,Boolean>, Map<String,Integer> )
Is there a better manner to implement properties file having key-value pairs as value using Spring/Spring Boot?
I want to create a property file where the key contains a couple of key-value pair as value.
I tried below implementation:-
Properties file:-
Fiat=model:pet,year:1996
Honda=model:dis,year:2000
And i have below class trying to read the properties file.
#Component
#PropertySources(#PropertySource("classpath:sample.properties"))
public class PropertiesExtractor {
#Autowired
private Environment env;
public String pullValue(String node) {
String value = env.getProperty(node);
System.out.println(value);//for Fiat, i get syso as **model:pet,year:1996**
}
}
I need to parse the values using java, to get the individual value. Is this the only way out to implement this.
Is there a better way to use nested property files in Java?
Create a Car object or something with a model and a year property. Then create something like this
#ConfigurationProperties("foo")
public class CarProperties {
private Map<String,Car> cars;
// Getters/Setters
}
Add add #EnableConfigurationProperties(CarProperties.class) in your main configuration class.
Then you can inject that config as follows:
foo.cars.Fiat.model=pet
foo.cars.Fiat.year=1996
foo.cars.Honda.model=dis
foo.cars.Honda.year=2000
There is more info in the doc.
You can use yaml files with spring as well:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml
This way, you can work with
Fiat:
model: pet
year: 1996
Honda:
model: dis
year: 2000
I have a text file which contain comma separated data which is the attribute of our bean.
e.g. name,age,gender,city,zipcode
We read the text file and we have a list which contain all the attribute. Here we need to create a dynamic Bean which contain the attribute based on that list which we get after reading text file, but we have different text files with different fields. So how should I create a dynamic bean which can contain the attributes according to the list which we will get after reading test file? Please give me some solution on this issue.
It isn't a dynamic Bean,
but I would use a HashMap:
HashMap<String, String> values = new HashMap<String, String>();
values.put("name", "Sebastian Blablabla");
values.put("city", "MyTown");
System.out.println(values.get("name"));
System.out.println(values.containsKey("city"));
System.out.println(values.containsKey("zipcode"));
Dynamic beans by Oracle use Maps too, look here:
http://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0210dynamicbeans01.html
I would just Use a Super- Class; Just like, i dont know..
public class Item