Home > Mobile >  How can I specify a javax constraint annotation message as an enum
How can I specify a javax constraint annotation message as an enum

Time:05-03

I would like to specify a javax constraint annotation message as an enum. Since the javax constraint message needs to be a String, I tried using enum#name() as follows:

import javax.validation.constraints.NotEmpty;

public class Test
{
    enum MessageKey {
        KEY_1,
        KEY_2
    }

    @NotEmpty(message = MessageKey.KEY_1.name())
    private String name;
}

However, this failed to compile:

C:\Users\GeoffAlexander\Documents\Java>javac -cp .\validation-api-2.0.1.Final.jar Test.java Test.java:10: error: element value must be a constant expression @NotEmpty(message = MessageKey.KEY_1.name())

Since enum#name() is declared as final, I expected the compiler to process MessageKey.KEY_1.name() as a constant. But it seems that it does not. Is there any way I can specify the enum constant as the message parameter (I don't need a non-enum workaround as I already know how to do that)?

CodePudding user response:

A work-around that we apply occasionally:

Inside that enum class, declare the desired key as String constant:

enum MessageKey {
    KEY_1(KEY_1_STR), KEY_1(KEY_2_STR);

    public static final KEY_1_STR = "KEY_1"; ...

    private final keyAsString;
    private MessageKey(String key) { keyAsString = key; }

    public String getKey() { return keyAsString; }
}

Now you can point your annotation to that STRING constant inside your enum.

Of course, that leaves you open to typos in the string constant itself. That one you can fix with a unit test that automatically checks all enum constants for their key and ensure it matches.

It is not nice, but when you want those two things: A) some enum and B) to use the enum constants as annotation, well: it does that.

(disclaimer: I just wrote down the above without running it through the compiler, consider it pseudo code that gives the idea, not a 100% correct implementation)

CodePudding user response:

No you cannot.

The only options available to you are non-enum constants, or some other workaround. In Java, a constant expression is the only permitted value of an annotation element. Here is the definition of a constant expression, but in short, a constant expression is only allowed to return primitives (int, char, etc.) or a String, and the expression itself has limits to what operations you can perform within.

Since enums are Objects and are not primitives or a String, they already break the first rule. And even if you tried to use Enum.name(), there is a list of rules that decides what is allowed in an expression, and Objects are not permitted. Therefore, you are blocked on both fronts.

As of May 2022, what you want is impossible to do in Java.

However, there is a decent chance that this changes in the future. We are/might be getting new primitive types and value objects. I imagine that when/if we get these, the rules for constant expressions may change.

  • Related