Bean definition is not loaded from the Spring applicationContext.xml file

91 Views Asked by At

I have some SQL queries stored in the applicationContext.xml file in the form of the Map

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<util:map id="queries" key-type="java.lang.String" value-type="java.lang.String">
    <description>Map contain SQL queries to handle ETL Framework database operations</description>
    <entry key="getJobById" value="SELECT * FROM etl_jobs WHERE job_id = ?"/>
    <entry key="getJobsByName" value="SELECT * FROM etl_jobs WHERE job_name LIKE ?"/>
    ...
</util:map>    
In my Java code I have the following:
@Repository
@ImportResource("classpath:applicationContext.xml")
public class EtlDataRepository {

    private static final Logger LOG = LoggerFactory.getLogger(EtlDataRepository.class.getName());

    @Autowired
    private JdbcTemplate jdbc;

    private Map<String, String> queries;
    ...
}

I do have setters and getters for this class as well. However, queries bean is not loaded when application starts, i.e. it is null. I had the very similar code written couple years ago and it was working perfectly fine. What has changed in Spring-boot from v.2.3 to v.3.2 to make it not working and how do I fix it?

Moving @ImportResource to the top, i.e. @SpringBootApplication did not change a thing. Adding @Autowired to the Map queries caused the following error:

*************************** APPLICATION FAILED TO START


Description:

Field queries in com.visa.vms.etl.daemon.dao.EtlDataRepository required a bean of type 'java.util.Map' that could not be found.

The injection point has the following annotations:

  • @org.springframework.beans.factory.annotation.Autowired(required=true)

The bean is defined in the applicationContext.xml file. It looks like this context is not being imported.

The very same code (with different content of map) was used in the older application with SpringBoot v.2.3 and was working without autowiring.

1

There are 1 best solutions below

2
xerx593 On BEST ANSWER

With @Qualifier("queries") I was able to "wire" the described (xml+) map.... like so:

package com.example.demo;

import java.util.Map;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource("classpath:applicationContext.xml")
public class Demo {
    public static void main(String[] args) {
        SpringApplication.run(Demo.class, args);
    }

    @Bean
    InitializingBean hello(/*@Autowired*/ @Qualifier("queries") Map<String, String> queries) {
        return () -> System.err.println(queries);
    }
}

... there is no strong argument, why it should not work in any Bean/Repository/Service.

Though, I could not reproduce the error so quickly: Omitting qualifier at least populates (somehow in a default quickstart) an empty map.


To reproduce "failed application start" we can use:

@Bean
InitializingBean hello2(Map x) {
  return () -> System.err.println(x);
}

, where nor:

  • (parameter) name is qualifying
  • (nor) generic type arguments declared.

It gives us (in a spring-boot quickstart):

...
***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method hello2 in com.example.demo.Demo required a single bean, but 5 were found:
        - queries: defined in unknown location
        - systemProperties: a programmatically registered singleton
        - systemEnvironment: a programmatically registered singleton
        - contextParameters: a programmatically registered singleton
        - contextAttributes: a programmatically registered singleton

@Value alternative

This is also possible:

//..somewhere in a spring bean (aware of applicationContext.xml)...
@Value("#{queries}") Map<String, String> queries;

... an (org.springframework...)@Value + SpEL for "'queries' bean" + matching field/parameter.