1

I have a class that shall contain data which is de-serialized from a JSON file. This data shall be available in my application, so I want to bind it as bean.

To keep the de-serialization logic and and the data structure together, I wanted to put the @Bean annotated factory method into the data class itself – like this:

@Configuration
public class MyData {

    // factory method
    @Bean
    public static MyData loadMyData(ResourceLoader resourceLoader) throws IOException {
        try (InputStream input = resourceLoader.getResource("classpath:data.json").getInputStream()) {
            return new ObjectMapper().readValue(input, MyData.class);
        } 
    }

    // data structure
    private Map<String, DataDetail> details;

    // ...
}

However this fails because @ComponentScan finds two bean definitions now:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.example.MyData' available: expected single matching bean but found 2: myData,loadMyData

I also tried to replace the @Configuration with @Component, but the result is the same.

Am I just missing the right annotation on the class, or is it just not possible to place the @Bean method in the bean class itself?

oberlies
  • 11,503
  • 4
  • 63
  • 110
  • take a look at [Best way to load some JSON files into a Spring Boot application](https://stackoverflow.com/q/34277392/217324) – Nathan Hughes Mar 18 '19 at 14:05
  • do you need two beans of same type? you can name them unique and `Autowire` the corresponding one – Ryuzaki L Mar 18 '19 at 14:40
  • No, I only want one bean. But so far I haven't figured out how to get this in the described scenario. – oberlies Mar 18 '19 at 15:11

2 Answers2

0

Basically i prefer layered architecture with spring boot, so with two different layers for Configuration and model, for example

package app.config

@Configuration
public class MyDataConfig {

// factory method
@Bean
public static MyData loadMyData(ResourceLoader resourceLoader) throws IOException {
    try (InputStream input = resourceLoader.getResource("classpath:data.json").getInputStream()) {
        return new ObjectMapper().readValue(input, MyData.class);
    } 
 }

}

package com.model

public class MyData {

// data structure
private Map<String, DataDetail> details;

    // ...
}
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
0

As Deadpool answered, you should separate the MyData class from the @Configurtion class.
@Configuration is meta-annotated with @Component so once you annotate MyData with @Configuration, Spring also relate it as a regular bean, and that makes the double defenition of the MyData beans.

Harel
  • 36
  • 6