This code is based on ScalaElResolver by Werner Punz.
I have stripped it down, so it just handles the conversion from a Scala Iterable
to a java.lang.Iterable
:
class SimpleScalaElResolver extends ELResolver {
override def getValue(elContext: ELContext, base: AnyRef,
prop: AnyRef): AnyRef = {
println(s"SimpleElResolver: getValue: Entering: $base.$prop")
if (base == null) {
null
} else {
val method = base.getClass.getDeclaredMethod(prop.toString)
if (method != null) {
val res = method.invoke(base)
if (res.isInstanceOf[Iterable[_]]) {
val iter = res.asInstanceOf[Iterable[_]]
println("getValue: Wrapping as Java iterable")
elContext.setPropertyResolved(true)
JavaConversions.asJavaIterable(iter)
} else {
null
}
} else {
null
}
}
}
This is sufficient to get it running using sbt
and its web plugin (which uses jetty
under the hood), even if all other methods remained "not yet implemented", like this:
override def getCommonPropertyType(elContext: ELContext, o: AnyRef): Class[_] = {
???
}
The other methods were not called in my case.
I've tested it only from within a .jspx
; as far as I know this should work with JSF
as well.
Example: If you have a class
class Model(val list: List[Int])
and in your controller
val model = new Model(List(1))
httpRequest.setAttribute("model", model)
you can access the instance in EL
<ul>
<c:forEach var="i" items="${ model.list }">
<li>
<c:out value="${ i }"/>
</li>
</c:forEach>
</ul>
so the property name in EL exactly matches the name of the val
in your model class. Otherwise you get a java.lang.NoSuchMethodException
.