2

I have the following yaml file

    proj:
     sms:
      gateway:
        username: d
        password: erer
        signature: e
        url: http://link.somelink.com
      actionKeyMap:
       OTP_GENERATOR: Value1
       CREATE_USER: Value2

I'm trying to bind the actionKeyMap/gateway property into a Java map and it doesn't works.

I've tried the following code

@Component
@ConfigurationProperties(prefix="proj.sms")
public class MessageResolver {

    //@Value("${proj.sms.actionKeyMap}")
    private Map<String, String> actionKeyMap;

ConfigurationProperties or Value annotation doesn't works.

Thomas Martin
  • 678
  • 8
  • 19
user3280711
  • 43
  • 1
  • 12

4 Answers4

1

Adding code as discussed in comments

Application.yml

proj:
  sms:
    gateway:
        username: d
        password: erer
        signature: e
        url: http://link.somelink.com
    actionKeyMap:
      OTP_GENERATOR: Value1
      CREATE_USER: Value2

Spring boot Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//@EnableConfigurationProperties
public class Application {

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

    }
}

MessageResolver.java

package hello;

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix="proj.sms")
public class MessageResolver {

    //@Value("${proj.sms.actionKeyMap}")
    private Map<String, String> actionKeyMap;

    @Value("${proj.sms.actionKeyMap.OTP_GENERATOR}")
    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }

    public Map<String, String> getActionKeyMap() {
        return actionKeyMap;
    }

    public void setActionKeyMap(Map<String, String> actionKeyMap) {
        this.actionKeyMap = actionKeyMap;
    }

}

GreetingController.java

package hello;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @Autowired
    MessageResolver messageResolver;

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {

        System.out.println(messageResolver.getTest());
        System.out.println(messageResolver.getActionKeyMap());
        return new Greeting(counter.incrementAndGet(),
                            String.format(template, name));
    }
}

Greeting.java (in case you try to build complete project)

package hello;

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}

URL http://localhost:8080/greeting

Console Output from GreetingController (sop on line 22 & 23)

Value1
{OTP_GENERATOR=Value1, CREATE_USER=Value2}
Shailesh Chandra
  • 2,164
  • 2
  • 17
  • 25
  • I cannot thank you enough, Shailesh. I was missing a get/set of the property. How come `@Value` annotation doesn't requires a get/set but `@ConfigurationProperties` does? Also, `@SpringBootApplication` enables scanning of `@ConfigurationProperties`? Phew! Thanks, man – user3280711 Sep 25 '19 at 05:47
  • 1
    This comment is for reference purpose - https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding Figured out the difference between `@ConfigurationProperties` and `@Value` – user3280711 Sep 25 '19 at 08:32
0

You can get information with this link on how to solve your problem: How to inject a Map using the @Value Spring Annotation?

it will look something like:

actionKeyMap: '{
  OTP_GENERATOR: "value1",
  CREATE_USER: "value2"
}'
EFOE
  • 609
  • 1
  • 10
  • 20
  • So when I try this I get the following exception - Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map': no matching editors or conversion strategy found – user3280711 Sep 24 '19 at 14:36
0

Try :(colon) intead of .(dot)

@Component
@ConfigurationProperties(prefix="proj:sms")
public class MessageResolver {

    @Value("${proj:sms:actionKeyMap}")
    private Map<String, String> actionKeyMap;
MangduYogii
  • 935
  • 10
  • 24
0

You just need to declare Gateway and ActionKeyMap class to match the ymlproperty. Or you can read the Spring Boot reference here, link.

@Component
@ConfigurationProperties(prefix="proj.sms")
public class MessageResolver {
    private Gateway gateway;
    private ActionKeyMap actionKeyMap;
    //getter/setter
}

``

public class Gateway {
    private String username;
    private String password;
    private String signature;
    private String url;
    //getter/setter
}

``

public class ActionKeyMap {
    private String OTP_GENERATOR;
    private String CREATE_USER;
    //getter/setter
}
Holinc
  • 641
  • 6
  • 17
  • OKay. I'll try to explain again. What I'm trying to achieve here is a simple Map of key-value pair that might change. So, having a property specific to each key is anyway a poor design. Also, this is a classic Class explosion problem, that I think we should avoid. – user3280711 Sep 24 '19 at 14:12
  • Of course you can bind to `Map` properties, reference here.https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding – Holinc Sep 25 '19 at 06:29