“Sometimes”, Scala creates
no
There are two things that CDI doesn’t like (which Scala “sometimes” generates):
1.
2.
To investigate and reproduce these problems I created a scala-cdi project at GitHub.
Compiles to:
Deploying this app in Weld will throw:
Which now compiles to:
Tip: To learn more about Scala programming, I recommend Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition.
public final
methods, although the .scala
source definesno
public final
method at all.There are two things that CDI doesn’t like (which Scala “sometimes” generates):
1.
public final
methods2.
public
fieldsTo investigate and reproduce these problems I created a scala-cdi project at GitHub.
public final method: The Bug
Referencing a parent field from a closure / inner class triggers this behavior:@RequestScoped @Named class IndexBean { private lazy val log = LoggerFactory.getLogger(classOf[IndexBean]) def testExecutor() = { val executor = Executors.newFixedThreadPool(4); executor.submit(new Runnable() { override def run(): Unit = log.debug("Executor is running") }) } }
$ javap -p IndexBean Compiled from "IndexBean.scala" public class com.soluvas.scalacdi.IndexBean extends java.lang.Object implements scala.ScalaObject{ private org.slf4j.Logger com$soluvas$scalacdi$IndexBean$$log; ... public final org.slf4j.Logger com$soluvas$scalacdi$IndexBean$$log();
org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437 Normal scoped bean class com.soluvas.scalacdi.IndexBean is not proxyable because the type is final or it contains a final method public final org.slf4j.Logger com.soluvas.scalacdi.IndexBean.com$soluvas$scalacdi$IndexBean$$log() - Managed Bean [class com.soluvas.scalacdi.IndexBean] with qualifiers [@Any @Default @Named]. at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:225) at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178) at org.jboss.weld.util.Proxies.getUnproxyableTypesExceptionInt(Proxies.java:193) at org.jboss.weld.util.Proxies.getUnproxyableTypesException(Proxies.java:167) at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:110)
public final method: Workaround
Create a final local variable to hold the parent instance’s value:def testExecutor() = { val executor = Executors.newFixedThreadPool(4); // this avoids 'log' becoming 'final' like: // private org.slf4j.Logger com$soluvas$scalacdi$IndexBean$$log; // public final org.slf4j.Logger com$soluvas$scalacdi$IndexBean$$log(); val log = this.log; executor.submit(new Runnable() { override def run(): Unit = log.debug("Executor is running") }) }
$ javap -p IndexBean Compiled from "IndexBean.scala" public class com.soluvas.scalacdi.IndexBean extends java.lang.Object implements scala.ScalaObject{ private org.slf4j.Logger log; private org.slf4j.Logger log();
public field
I’m not able to reproduce this yet...Tip: To learn more about Scala programming, I recommend Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition.