I have added a map in my values.yaml file like below
defaultview:
journey:
ce5f164c-ae0f-11e7-9220-c7137b83fb6a: 45
abc: -1
pqr: 30
I read this property in configmap like below
defaultview.journey: {{ .Values.defaultview.journey }}
When I check configmap I see entry like below in cm
defaultview.journey:
----
map[abc:-1 ce5f164c-ae0f-11e7-9220-c7137b83fb6a:45 pqr:30]
Java class is trying to bind this property into a Map<String,Integer> like below
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Data
@Component
@ConfigurationProperties(prefix = "defaultview")
public class JourneyViewConfig {
private Map<String, Integer> Journey = new HashMap<>();
}
I see error thrown while spring boot startup
Failed to bind properties under 'defaultview.journey' to java.util.Map<java.lang.String, java.lang.Integer>:\\n\\n Property: defaultview.journey\\n Value: \\\"map[abc:-1 ce5f164c-ae0f-11e7-9220-c7137b83fb6a:45 pqr:30]\\\"\\n Origin: \\\"defaultview.journey\\\" from property source \\\"<cm name>\\\"\\n Reason: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.Integer>
Is there a way to inject Map directly from configmap to spring boot?
Edit 1: I am able to read the values in map by adding this dirty code
private Map<String, Integer> parseConfigValue(String configValue) {
Map<String, Integer> resultMap = new HashMap<>();
String trimmedInput = configValue.trim();
if (trimmedInput.startsWith("map[")) {
trimmedInput = trimmedInput.substring(4, trimmedInput.length() - 1);
String[] pairs = trimmedInput.split(" ");
for (String pair : pairs) {
String[] keyValue = pair.split(":");
if (keyValue.length == 2) {
String key = keyValue[0].trim();
Integer value = Integer.parseInt(keyValue[1].trim());
resultMap.put(key, value);
}
}
Is there a more subtle way of doing this?
This line is problematic:
defaultview.journey: {{ .Values.defaultview.journey }}
You're trying to include a structured variable as a simple string, so this is resulting in a ConfigMap that looks like:
data:
defaultview.journey_broken: map[abc:-1 ce5f164c-ae0f-11e7-9220-c7137b83fb6a:45 pqr:30]
That's not useful, as it's neither valid YAML nor JSON and probably isn't what your application is expecting.
You're going to need to use the toYaml
function to render your structured variable as a block of YAML text. For example:
data:
defaultview.journey: |
{{ indent 4 (.Values.defaultview.journey | toYaml) }}
Which results in:
data:
defaultview.journey: |
abc: -1
ce5f164c-ae0f-11e7-9220-c7137b83fb6a: 45
pqr: 30