I have a class that have a number of constants:
public class SecurityConstants {
private static final String HAS_ROLE_TEMPLATE = "hasRole('%s')";
public static final String ROLE_USER_INTERNAL = "ROLE_USER_INTERNAL";
public static final String HAS_ROLE_USER_INTERNAL = String.format(HAS_ROLE_TEMPLATE, ROLE_USER_INTERNAL);
}
If I then try to use HAS_ROLE_USER_INTERNAL as @PreAuthorize annotation attribute value like this @PreAuthorize(SecurityConstants.HAS_ROLE_USER_INTERNAL) compiler fails with:
The value for annotation attribute
PreAuthorize.value must be a constant
expression
However if I change HAS_ROLE_USER_INTERNAL to be a simple String it works just fine:
public static final String HAS_ROLE_USER_INTERNAL = "hasRole('ROLE_USER_INTERNAL')";
What’s the problem with using String.format()? Field is static and final, what can possibly go wrong?
The value of
String.format()isn’t known at compile time, whereas aStringliteral is.Since the annotations are metadata on the compiled class, their values must be known by the time the compiler generates the final .class file. Since
String.format()‘s value will only be known once the code is actually run, the compiler won’t let you use it as part of an annotation.