I've been building out some annotated domain classes in Scala 2.8.0 using Hibernate Annotations 3.4.0. It's been working fine, except that there are certain annotations which take an array as a parameter. For example, here's a Java annotation that I want to express in Scala:
@OneToMany(mappedBy="passport_id", cascade=CascadeType.PERSIST)
However, the annotation requires an array/set as input:
[ERROR] .../Passport.scala:50: error: type mismatch;
[INFO] found : javax.persistence.CascadeType(value PERSIST)
[INFO] required: Array[javax.persistence.CascadeType]
[INFO] @OneToMany(mappedBy="passport_id", cascade=CascadeType.PERSIST)
I've tried various parentheses, square/angle/curly brackets, and so on:
@OneToMany(mappedBy="passport_id", cascade=(CascadeType.PERSIST))
@OneToMany(mappedBy="passport_id", cascade=[CascadeType.PERSIST])
@OneToMany(mappedBy="passport_id", cascade=<CascadeType.PERSIST>)
@OneToMany(mappedBy="passport_id", cascade={CascadeType.PERSIST})
... but unfortunately I've reached the end of my understanding of Scala/Java annotations. Help is appreciated.
I'll add a few snippets from the spec to explain why Rex's solution works.
For Scala on the JVM, arguments to annotations that will be retained within the generated class must be constant expressions:
Instances of an annotation class inheriting from trait
scala.ClassfileAnnotation will be stored in the generated class files. ... Additionally, on both Java and .NET, all constructor arguments must be constant expressions.
What are constant expressions?
6.24 Constant Expressions Constant expressions are expressions that the
Scala compiler can evaluate to a
constant. The definition of “constant
expression” depends on the platform,
but they include at least the
expressions of the following forms:
- A literal of a value class, such as an integer
- A string literal
- A class constructed with Predef.classOf (§12.4)
- An element of an enumeration from the underlying platform
- A literal array, of the form Array(c1, . . . , cn), where all
of the ci ’s are themselves constant
expressions
- An identifier defined by a constant value definition (§4.1).
You should also be able to refactor the argument to a final val
. This doesn't seem to work for Arrays, however. I'll raise a bug.
class T(value: Any) extends ClassfileAnnotation
object Holder {
final val as = Array(1, 2, 3)
final val a = 1
}
@T(Holder.a)
@T(Holder.as) // annot.scala:9: error: annotation argument needs to be a constant; found: Holder.as
class Target
From Rex Kerr:
@OneToMany(mappedBy="passport_id", cascade=Array(CascadeType.PERSIST))
This worked. Thanks.