Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should mapping value be declared in a constant or as an enum?

I see this scattered throughout code base:

@RequestMapping(value = "myValue")

I would prefer to use something like this:

@RequestMapping(value = Constants.myValue)

It seems to break DRY using the actual String value within @RequestMapping instead of constant. But is this good code practice? Should I use an enum instead? I may need to use Constants.myValue elsewhere in the code base.

like image 741
blue-sky Avatar asked Jul 31 '12 13:07

blue-sky


1 Answers

Should I use an enum instead?

You can't. Annotation variables must be compile-time constants. Enums and String literals both are, but you can't create an enum that is a String and @RequestMapping needs a String (and if your enum has a method that returns a String or a String field, that's not a compile-time constant). Since there are multiple rounds of annotation processing it does work when the constant is in another class.

That said: yes, I'd say using a dedicated constants class (perhaps several, for different types of constants) is a good practice that I use whenever I can (and it works with annotations as long as the constant a) is not defined inside the same compilation unit that has the annotation and b) is initialized in the declaration (as opposed to a static initializer block)).

Here's an example:

Controller

@Controller @RequestMapping(value = Mappings.CUSTOMER_PAGE)
public class CustomerPageController{
    // methods here
}

Constants class

public static final class Mappings{
    private Mappings(){}
    public static final String CUSTOMER_PAGE = "path/to/customer/page"
    // more constants
}

And here are some versions that won't work:

a)

@Controller @RequestMapping(value = CUSTOMER_PAGE)
public class CustomerPageController{
    private static final String CUSTOMER_PAGE = "path/to/customer/page";
}

This won't compile because the annotation references a constant inside the class it annotates. This can't work because during compilation, annotations are processed in a separate round before the rest of the code, while the class needs the annotation to already be processed for compilation (i.e. there's a circular dependency between annotation and constant)

b)

public static final class Mappings{
    private Mappings(){}
    public static final String CUSTOMER_PAGE;
    static{
        CUSTOMER_PAGE = "path/to/customer/page"
    }

    // more constants
}

Although this is a static final field, it is not a compile-time constant, hence it can't be used as an annotation parameter

like image 197
Sean Patrick Floyd Avatar answered Oct 16 '22 17:10

Sean Patrick Floyd