Reputation: 6332
I have defined a simple scala annoation and use it to annotate my case class Person:
package com.my
import scala.annotation.StaticAnnotation
@scala.annotation.meta.field
class Description(value: String) extends StaticAnnotation{
}
Then I use it in my Person class:
package com.my
import scala.beans.BeanProperty
case class Person(
@Description(value = "name00")
name: String,
@Description(value = "age00")
age: Int,
@BeanProperty
xyz: String = "xyz"
)
object Person {
def main(args: Array[String]): Unit = {
val p = Person("abc", 21)
classOf[Person].getDeclaredFields.foreach {
field =>
field.setAccessible(true)
val name = field.getName
val value = field.get(p)
//annotations always return empty array
val annotations = field.getDeclaredAnnotations
annotations.foreach {
annotation =>
val tpe = annotation.annotationType()
println(tpe)
}
println(s"name is $name, value is: $value")
}
}
}
In the main method of Person object, the annotations array is always empty, I would like to ask how to get the annoation information defined on the field.
Upvotes: 1
Views: 1176
Reputation: 51658
Firstly, annotations written in Scala are accessible in sources (if the annotations extend scala.annotation.Annotation
) and class files (if if the annotations extend scala.annotation.StaticAnnotation
). In order to be accessible at runtime the annotations must be written in Java
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
String value();
}
How to use Scala annotations in Java code
Why annotations written in Scala are not accessible at runtime?
https://www.reddit.com/r/scala/comments/81qzs2/how_to_write_annotations_in_scala/
Alternatively you can use the original @Description
(written in Scala and extending StaticAnnotation
) but then you have to access it at runtime via Scala reflection rather than Java reflection.
Secondly, you misuse meta-annotations (@scala.annotation.meta.field
). They should annotate not the definition of @Description
but its applications.
import scala.annotation.meta.field
case class Person(
@(Description @field)(value = "name00")
name: String,
@(Description @field)(value = "age00")
age: Int,
@BeanProperty
xyz: String = "xyz"
)
Annotating case class parameters
How can I reflect on a field annotation (Java) in a Scala program?
Calling a method from Annotation using reflection
Output:
interface Description // appears
name is name, value is: abc
interface Description // appears
name is age, value is: 21
name is xyz, value is: xyz
With Scala reflection you can do
import scala.annotation.StaticAnnotation
import scala.beans.BeanProperty
import scala.annotation.meta.field
import scala.reflect.runtime.universe._
class Description(value: String) extends StaticAnnotation
case class Person(
@(Description @field)(value = "name00")
name: String,
@(Description @field)(value = "age00")
age: Int,
@BeanProperty
xyz: String = "xyz"
)
def main(args: Array[String]): Unit = {
val p = Person("abc", 21)
typeOf[Person].decls
.collect { case t: TermSymbol if t.isVal => t.annotations }
.foreach(println)
}
//List(Description @scala.annotation.meta.field("name00"))
//List(Description @scala.annotation.meta.field("age00"))
//List(scala.beans.BeanProperty)
Upvotes: 2