Reputation: 12063
In my project I use XML-based configurations and I'm trying to read the application.yml file
application.yml
vtp:
config:
priority:
2:
country: 'US'
countryFriend: ['UK','AG']
3:
country: 'IN'
countryFriend: ['UK','AG']
4:
country: 'PO'
countryFriend: ['NL']
5:
country: 'KN'
countryFriend: ['DN']
I am able to read it using Spring Boot by creating a POJO class to map the properties like below
@Configuration
@ConfigurationProperties(prefix = "vtp.config")
@PropertySource(value = "classpath:application.yml")
public class MeraPriorityConfig {
private Map<String, Config> priority;
public Map<String, Config> getPriority() {
return priority;
}
public void setPriority(Map<String, Config> priority) {
this.priority = priority;
}
}
How can I do the same using an XML-based configuration?
Upvotes: 2
Views: 3107
Reputation: 13289
What Do you mean with "all data in a Map"!?
The discussed/linked solution can expose your yaml file as a java.util.Properties
(, which is a Map<String, Object>
"per se").
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.my</groupId>
<artifactId>spring-xml-config-with-yaml</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.7</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
(src/main/resources/)application.yaml:
Same as OP!
src/main/resources/applicationContext.xml (simplified):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
<property name="resources" value="classpath:application.yaml"/>
</bean>
</beans>
Then just a test (main):
package org.my.springxmlconfig;
import java.util.Properties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringXmlConfigMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Properties propsBean = context.getBean("yamlProperties", Properties.class);
System.err.println(propsBean);
}
}
Prints (unformatted):
{
vtp.config.priority[3].country=IN,
vtp.config.priority[4].countryFriend[0]=NL,
vtp.config.priority[2].countryFriend[1]=AG,
vtp.config.priority[2].countryFriend[0]=UK,
vtp.config.priority[5].countryFriend[0]=DN,
vtp.config.priority[2].country=US,
vtp.config.priority[4].country=PO,
vtp.config.priority[5].country=KN,
vtp.config.priority[3].countryFriend[0]=UK,
vtp.config.priority[3].countryFriend[1]=AG
}
In a "normal spring usage", we can refer to them:
@Autowired
@Qualifier("yamlProperties")// we need qualifier already due to "systemProperties"
java.util.Properties yamlProps;
Of course this solution is not as elegant as spring-boot's, but it correctly depicts the yaml structure. The resulting map is "flat", but structure is achieved through (more hierarchical) "keys".
To achieve "more hierarchical" map, I'd:
YamlMapFactoryBean
!!Adding this to our config xml:
<bean id="yamlMap" class="org.springframework.beans.factory.config.YamlMapFactoryBean">
<property name="resources" value="classpath:application.yaml"/>
</bean>
Doing this:
import org.apache.commons.collections4.MapUtils;
// ...
Map<String, Object> mapBean = context.getBean("yamlMap", Map.class);
MapUtils.debugPrint(System.err, "yamlMap", mapBean);
(Only for (quick) debug (pretty) print,) we add this:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version> <!-- resp. latest -->
</dependency>
..then console prints also (formatted):
yamlMap =
{
vtp =
{
config =
{
priority =
{
[2] =
{
country = US java.lang.String
countryFriend = [UK, AG] java.util.ArrayList
} java.util.LinkedHashMap
[3] =
{
country = IN java.lang.String
countryFriend = [UK, AG] java.util.ArrayList
} java.util.LinkedHashMap
[4] =
{
country = PO java.lang.String
countryFriend = [NL] java.util.ArrayList
} java.util.LinkedHashMap
[5] =
{
country = KN java.lang.String
countryFriend = [DN] java.util.ArrayList
} java.util.LinkedHashMap
} java.util.LinkedHashMap
} java.util.LinkedHashMap
} java.util.LinkedHashMap
} java.util.LinkedHashMap
Thx also to: Multi-line pretty-printing of (nested) collections in Java
Upvotes: 3
Reputation: 347
Briefly speaking, you achieve this by 3 steps: 1) rewrite config in bean xml; 2) Define class to match the bean definition, 3) get bean by code from context.
I made a working sample project, can be found here: https://github.com/forrest1g/spring-xml-demo
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="countryConfigBean" class="com.itranswarp.learnjava.VTPConfig">
<property name="countries">
<list>
<ref bean="US"/>
<ref bean="IN" />
<ref bean="PO" />
<ref bean="KN" />
</list>
</property>
</bean>
<bean id="US" class="com.itranswarp.learnjava.CountryConfig">
<property name="priority" value="2"/>
<property name="country" value="US"/>
<property name="countryFriends" value="['UK','AG']"/>
</bean>
<bean id="IN" class="com.itranswarp.learnjava.CountryConfig">
<property name="priority" value="3"/>
<property name="country" value="IN"/>
<property name="countryFriends" value="['UK','AG']"/>
</bean>
<bean id="PO" class="com.itranswarp.learnjava.CountryConfig">
<property name="priority" value="4"/>
<property name="country" value="PO"/>
<property name="countryFriends" value="['NL']"/>
</bean>
<bean id="KN" class="com.itranswarp.learnjava.CountryConfig">
<property name="priority" value="5"/>
<property name="country" value="KN"/>
<property name="countryFriends" value="['DN']"/>
</bean>
</beans>
Further more, you can find some sample about how to define collection in bean xml here: how to define collection
Output like:
priority: 2, country: US, countryFriends: ['UK','AG']
priority: 3, country: IN, countryFriends: ['UK','AG']
priority: 4, country: PO, countryFriends: ['NL']
priority: 5, country: KN, countryFriends: ['DN']
Upvotes: 0