10

I am writing Java code that uses Jackson for JSON serialization. One annotation that I must use before one my classes is @JsonTypeName(/*Insert string here*/), in order to give an object of this class a unique identifier for serialization. In my current code, we set the String argument by using a global constant from another class. Example:

public class AnnotationValues {
    private static final String id1 = "1";
    private static final String id2 = "2";
    private static final String id3 = "3";
    // And so on...
}

Using this class, our annotation would look like @JsonTypeName(AnnotationValues.id1). I personally do not think that this is a very robust coding style, to use a class of global String constants. This would become annoying once my application needs to handled a larger quantity of JSON messages and thus require many different identifiers. I naturally would solve this problem, in general, by using an enum. I would replace the class with:

public enum AnnotationValues {
    ID1("1"),
    STATS_RESPONSE("2"),
    SESSION_RESPONSE("3"),
    /* Add more... */;
    public final String value;
    private AnnotationValues(String value) {
        this.value = value;
    }
}

Using this enum, I want to write @JsonTypeName(AnnotationsValues.ID1.value) as my annotation. But this doesn't work. I get this error message: "The value for annotation attribute JsonTypeName.value must be a constant expression". A simple Google/SOF search lead me to this SOF post telling me why this was an error; a String value for an annotation parameter must be a constant. Pretty annoying that I can't use an enum.

Does anyone else run into this problem? What is the accepted solution for this type of problem? Am I really supposed to use a long list of String constants for my annotations? Is there any way I can salvage using my Enum? Anything else?

Community
  • 1
  • 1
ecbrodie
  • 11,246
  • 21
  • 71
  • 120
  • Sorry but how is this _not_ a duplicate of that post you quote? http://stackoverflow.com/questions/3271659/use-enum-type-as-value-parameter-for-rolesallowed-annotation – Gray Sep 27 '12 at 17:43

2 Answers2

7

I really wish I or someone else could give you a different answer, but no, there is no other way that works better. In cases like this, we're all stuck using a class full of static final Strings. The way you tried to make it work ought to work, but it doesn't. For now, this is just the way it is in Java. I ran into this problem myself once, and I too was annoyed to find that Enums can't be treated like constant expressions. I feel your pain and, again, I wish I could give you a different answer.

James Dunn
  • 8,064
  • 13
  • 53
  • 87
-1

As suggested by the other answer, no, this is not possible with Java annotations.

But I wanted to ask this: why do you think use of Enum would be better than using String constants? To me the approaches look similar, and for sheer simplicity, what would be the point of adding Enum wrapper? Reference is similar in both cases, and actual constants are stored in a centralized place which has its benefits, so that you can share same Strings.

So I don't quite understand "do not think that this is a very robust coding style," comment, or at least not how use of additional do-nothing Enum wrapper would improve design.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • When you say something must be a specific Enum, then you restrict the possible inputs for a given method or annotation in this case. If you have to use String constants, than the strings could come from anywhere and code completion won't give you the obvious choices from the Enum as it would if you could strongly type it to an Enum type. – Novaterata Aug 29 '16 at 20:25
  • @novaterata Constants would all be within specific container class, so auto-completion would work just fine. And while true that IDE (or compiler) could not prevent you from passing arbitrary Strings from somewhere else, it really seems like an attempt to solve a problem that does not really exist. – StaxMan Aug 30 '16 at 01:09