1

I'm trying to create a Map<Integer,List<Integer>> variable into Java service.

I have this .yml:

my:
  data:
    '{
      1:[1,2,3],
      2:[1,2,3]
    }'

And into Java code:

@Value("#{${my.data}}")
protected Map<Integer,List<Integer>> bar;

But it fails when I run the project.

Actually the error thrown is something like:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'controller' defined in file ...

But it has to be by dependency injection, it fails when create the @Value in the @Service and the error is propagated. Also I have tested these values

my:
  data:
    '{
      1:
      - 1
      - 2,
      2:
      - 1
    }'

And it creates a lists with values -3 and -1.

| key | value |
+-----+-------+
|  1  |  [-3] |
|  2  |  [-1] |
+-----+-------+

So the error thrown before has to be due to the definition of the list in the first yml.

Also I've tested using List<Integer> and int[] into the Map object.

So, what's the correct syntax to create Map<Integer, List<Integer>>? I assumed it was like a JSON object { key: [v1, v2] } but it seems to fails.

Thanks in advance.

J.F.
  • 13,927
  • 9
  • 27
  • 65
  • Are you aware that you are giving your data as single string and evaluate it as Spring Expression, whose syntax is nowhere near JSON/YAML? Is this on purpose? – flyx Nov 16 '21 at 16:44
  • In general, complex values should be loaded via `@ConfigurationProperties` and it is unclear why you give the hard requirement of doing it via `@Value`. Would you drop that requirement, [this question](https://stackoverflow.com/q/24917194/347964) would give you multiple answers for different use-cases. – flyx Nov 16 '21 at 16:54
  • I have used this way (created JSON as a string) because an answer in the same link you provide ([here](https://stackoverflow.com/a/65762810/13464279)). If there is another way using `@Value` please tell me. Also use `@Value` instead of `@ConfigurationProperties` is for simplicity. – J.F. Nov 16 '21 at 18:05

1 Answers1

1

With @Value annotation:

  1. You should not map (yaml or properties "map") keys to Integer, prefer String.

  2. (Problem) Nesting Lists...

..still, I am quite sure it is possible with (crazy SpEL(l) @Value).

baeldung-article


But Type-safe Configuration Properties produce nice results quickly:

App.java:

@SpringBootApplication
@ConfigurationPropertiesScan
public class App {

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }

  @Bean
  CommandLineRunner runner(@Autowired My bar) {
    return args ->  System.out.println(bar);
  }
}

My.java:

@ConfigurationProperties("my")
public class My {
    private Map<Integer, List<Integer>> data = new HashMap<>();
    // Getter + Setter!!!
}

With this "fixed" yaml:

my:
  data: {
    1: [1,2,3],
    2: [1,2,3]
  }

Prints:

My(data={1=[1, 2, 3], 2=[1, 2, 3]})

EDIT:

The "best", I got with @Value so far, is:

@Value("#{${other.data}}") Map<?, ?> other; // raw map!! :-)

with this yaml(-like):

other:
  data: '{
   1: ''[1,2,3]'',
   2: ''[1,2,3]''
  }'

Prints:

{1=[1,2,3], 2=[1,2,3]}

(jdk:8, maven:3.8.2, spring-boot:2.5.6)

xerx593
  • 12,237
  • 5
  • 33
  • 64
  • Thanks, I've tested the link but it fails to create a list... I don't know if it is possible to do it using `@Value`. Also the other way provided works, thanks for the answer but I hope there is a possible way to do it with `@Value`. – J.F. Nov 16 '21 at 18:08