Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot bind @Value to Enum case insensitive

Enum

public enum Property {
    A,
    AB,
    ABC;
}

Field

@Value("${custom.property}")
protected Property property;

application.properties (lower case)

custom.property=abc

When I'm running application I have an error:

Cannot convert value of type [java.lang.String] to required type [com.xxx.Property]: no matching editors or conversion strategy found.

Whereas (upper case):

custom.property=ABC

Works fine.

Is there a way to bind the value case insensitive? Like ABC, Abc, AbC, abc any pattern should work.

NOTE: I saw this question - Spring 3.0 MVC binding Enums Case Sensitive but in my case I have over 10 enums/values (and expect to have more) classes and to implement 10 different custom property binders would be painful, I need some generic solution.

like image 319
Mikhail Kholodkov Avatar asked Feb 22 '16 23:02

Mikhail Kholodkov


People also ask

How do I make enum insensitive in spring boot?

Spring boot custom enum converter – case insensitive You can create a custom enum converter to accept small case enum values in the URI. For example, the following StringToDirectionEnumConverter converts the input string to uppercase and then performs the valueof method call.

Can we use @value in enum?

No, it's not. The purpose for an Enum is to give us mapped data (fixed set of values) with limited scope. If we would to use @Value in Java enums, it would take the purpose of the enum away in the first place.

Are enums values case sensitive?

Enum 's valueOf(String) Method Careful, the strings passed to valueOf are case sensitive!

Can you use == for enums?

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.


2 Answers

@Value and @ConfigurationProperties features do not match. I couldn't stress enough how @ConfigurationProperties is superior.

First, you get to design your configuration in a simple POJO that you can inject wherever you want (rather than having expressions in annotation that you can easily break with a typo). Second, the meta-data support means that you can very easily get auto-completion in your IDE for your own keys.

And finally, the relaxed binding described in the doc only applies to @ConfigurationProperties. @Value is a Spring Framework feature and is unaware of relaxed binding. We intend to make that more clear in the doc.

TL;DR abc works with @ConfigurationProperties but won't with @Value.

like image 80
Stephane Nicoll Avatar answered Oct 18 '22 19:10

Stephane Nicoll


A problem with ConfigurationPropertis (afaik) is that you cannot use constructor injection, and your class has to be mutable.

A workaround (or hack if you like) would be to use SpEL to uppercase the property before looking it up, like this:

@Value("#{'${custom.property}'.toUpperCase()}") Property property

This should work since enums instances are constants, and should always be defined in uppercase: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

like image 45
Morten Berg Avatar answered Oct 18 '22 20:10

Morten Berg