scala annotation argument needs to be constant but final val does not make it
In this snippet,
@SwaggerDefinition(...authorizationUrl =
SecurityConstants.authorizationUrl)
and given that
final object SecurityConstants {
final val authorizationUrl: String =..
}
(only one of the two finals should be ok, but still) I was expecting/hoping that this would compile with 2.12.3 but it is however giving "annotation argument needs to be a constant; found: SecurityConstants.authorizationUrl [error] authorizationUrl = SecurityConstants.authorizationUrl,"
Also calling Java static method System.getenv("a") in annotation brings the same error, that is
@SwaggerDefinition(...authorizationUrl = System.getenv("a"))
Please help, Nicu M
Solution 1:
final val
references can be used as Java annotation arguments under two conditions:
- The value assigned to the
final val
must be a literal. - You must not specify the type of your
final val
explicitly.
So, this will work:
final val AuthorizationUrl = "http://something.com"
but these will not work:
final val AuthorizationUrl = "http://something.com".trim
final val AuthorizationUrl: String = "http://something.com"
The condition no. 2 may seem especially weird but it's required for the compiler to internally retain the information that the final val
is holding not just a String
but some particular literal string value (the compiler must infer a literal type).
Solution 2:
It is really important what is behind ..
in the
final val authorizationUrl: String =..
In Scala and Java annotation arguments must be compile-time constants rather than just "final". So System.getenv("a")
(or any other function call) directly or via intermediate val
will not do it as this is not a compile-time constant. This is done that way because annotations are designed to be introspectable at the compile time i.e. if you just have a .class
file, you must be able to get the value of all the fields of the annotation. So the compiler must know all the values at the compile time.
Update
Actually Swagger itself relies on the compile-time introspection. So what exactly did you expect it to do with your System.getenv
call? What specification Swagger should have generated for such annotation? And why do you need it at all? AFAIU if you have several environments, you should put URLs of the production (i.e. the one accessed by outside users) into the definition.