PAA
PAA

Reputation: 12063

How to read application.yml in Spring XML configurations?

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

Answers (2)

xerx593
xerx593

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:


EDIT!:

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

forrestg
forrestg

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

Related Questions