Reputation: 618
My application has nested properties stored in applicaion.yml file.
I want to map those properties to POJO at the application boot-up.
Application.yml:
demo:
- A:
- type: A
prop1: 1
prop2: 2
proop3: 3
- type: B
prop1: 1
prop2: 2
proop3: 3
- B:
- type: A
prop1: 1
prop2: 2
proop3: 3
- type: B
prop1: 1
prop2: 2
proop3: 3
In order to achieve that, I am using below annotations:
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("demo")
Class Demo:
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("demo")
public class Demo {
@JsonProperty("A")
private List<A> a = null;
@JsonProperty("B")
private List<B> b = null;
@JsonProperty("A")
public List<A> getA() {
return a;
}
@JsonProperty("A")
public void setA(List<A> a) {
this.a = a;
}
@JsonProperty("B")
public List<B> getB() {
return b;
}
@JsonProperty("B")
public void setB(List<B> b) {
this.b = b;
}
@Override
public String toString() {
return "Demo [a=" + a + ", b=" + b + "]";
}
}
Class A:
public class A {
@JsonProperty("type")
private String type;
@JsonProperty("prop1")
private Integer prop1;
@JsonProperty("prop2")
private Integer prop2;
@JsonProperty("proop3")
private Integer proop3;
@JsonProperty("type")
public String getType() {
return type;
}
@JsonProperty("type")
public void setType(String type) {
this.type = type;
}
@JsonProperty("prop1")
public Integer getProp1() {
return prop1;
}
@JsonProperty("prop1")
public void setProp1(Integer prop1) {
this.prop1 = prop1;
}
@JsonProperty("prop2")
public Integer getProp2() {
return prop2;
}
@JsonProperty("prop2")
public void setProp2(Integer prop2) {
this.prop2 = prop2;
}
@JsonProperty("proop3")
public Integer getProop3() {
return proop3;
}
@JsonProperty("proop3")
public void setProop3(Integer proop3) {
this.proop3 = proop3;
}
@Override
public String toString() {
return "A [type=" + type + ", prop1=" + prop1 + ", prop2=" + prop2 + ", proop3=" + proop3 + "]";
}
}
Class B
public class B {
@JsonProperty("type")
private String type;
@JsonProperty("prop1")
private Integer prop1;
@JsonProperty("prop2")
private Integer prop2;
@JsonProperty("proop3")
private Integer proop3;
@JsonProperty("type")
public String getType() {
return type;
}
@JsonProperty("type")
public void setType(String type) {
this.type = type;
}
@JsonProperty("prop1")
public Integer getProp1() {
return prop1;
}
@JsonProperty("prop1")
public void setProp1(Integer prop1) {
this.prop1 = prop1;
}
@JsonProperty("prop2")
public Integer getProp2() {
return prop2;
}
@JsonProperty("prop2")
public void setProp2(Integer prop2) {
this.prop2 = prop2;
}
@JsonProperty("proop3")
public Integer getProop3() {
return proop3;
}
@JsonProperty("proop3")
public void setProop3(Integer proop3) {
this.proop3 = proop3;
}
@Override
public String toString() {
return "B [type=" + type + ", prop1=" + prop1 + ", prop2=" + prop2 + ", proop3=" + proop3 + "]";
}
}
Main Class
@SpringBootApplication
@ComponentScan(basePackages = {"com.microservice.*"})
@EnableJpaRepositories("com.microservice.*")
@EntityScan("com.microservice.*")
public class MainApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MainApplication.class);
app.run();
System.out.println("step 1");
Demo config = new Demo();
System.out.println("name: " + config);
}
public void run(String... args) throws Exception {
System.out.println("step 2");
}
}
But I am getting below o/p:
step 1
name: Demo [a=null, b=null]
Upvotes: 1
Views: 18110
Reputation: 990
When you create instanse of your properties POJO manually, Spring doesn't know about it and properties binding doesn't happens.
SpringApplication app = new SpringApplication(MainApplication.class);
app.run();
System.out.println("step 1");
Demo config = new Demo(); // Not a Spring managed bean!
System.out.println("name: " + config);
}
Instead of annotating configuration with @EnableConfigurationProperties
, you could make Demo
a bean, as shown in Type-safe Configuration Properties.
@Component
@ConfigurationProperties("demo")
public class Demo {
...
}
And then you could get Demo
bean from context:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class, args);
Demo demo = (Demo) context.getBean("demo");
System.out.println(demo.getName());
}
}
UPD: there must be no hyphen before 'a' and 'b':
demo:
a:
- type: A
prop1: 1
prop2: 2
proop3: 3
- type: B
prop1: 1
prop2: 2
proop3: 3
b:
- type: B
prop1: 1
prop2: 2
proop3: 3
UPD2: Answer to comment. You can build JSON from Demo
bean with ObjectMapper
:
@SpringBootApplication
public class MainApplication {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
public static void main(String[] args) throws JsonProcessingException {
...
ObjectMapper objectMapper = (ObjectMapper) context.getBean("objectMapper");
System.out.println(objectMapper.writeValueAsString(demo));
}
}
With spring-boot-starter-web
there no need for additional dependencies. Else, you could add jackson:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.0.1</version>
</dependency>
Upvotes: 5
Reputation: 470
From Mikhail answer just write json using Jackson ObjectMapper and you get your json format:
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(YamlTestApplication.class, args);
Demo demo = (Demo) context.getBean("demo");
System.out.println("name: " + demo);
ObjectMapper mapper = new ObjectMapper();
try {
String test = mapper.writeValueAsString(demo);
System.out.println("json: "+test);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
output:
name: Demo [a=[A [type=A, prop1=1, prop2=2, proop3=3], A [type=B, prop1=1, prop2=2, proop3=3]], b=[B [type=A, prop1=1, prop2=2, proop3=3], B [type=B, prop1=1, prop2=2, proop3=3]]]
json: {"A":[{"type":"A","prop1":1,"prop2":2,"proop3":3},{"type":"B","prop1":1,"prop2":2,"proop3":3}],"B":[{"type":"A","prop1":1,"prop2":2,"proop3":3},{"type":"B","prop1":1,"prop2":2,"proop3":3}]}
Upvotes: 0
Reputation: 743
It's incorrect in you yml
file.You can read the reference onto Merging YAML lists
,link here.
I write a demo and it works.
demo:
a:
b:
prop1: prop1
prop2: prop2
blist:
- prop1: prop1
prop2: prop2
alist:
- b:
prop1: prop1
prop2: prop2
blist:
- prop1: prop1
prop2: prop2
- b:
prop1: prop1
prop2: prop2
``
@ConfigurationProperties(prefix = "demo")
public class Demo {
private A a;
private List<A> alist;
// omitted getter/setter
}
``
public class A {
private B b;
private List<B> blist;
// omitted getter/setter
}
``
public class B {
private String prop1;
private String prop2;
// omitted getter/setter
}
Upvotes: 1
Reputation: 743
If you would like to read properties from a .yml
or .properties
file I propose you to create a class it could be called PropertiesBooter
where you would keep all your values retrieved from those files. To retrieve a value from a properties file you can write
@Value("${value}")
private String
Upvotes: 0