Tuesday, November 24, 2009

Scala is not mature enough for Weld

Scala is not mature enough for Weld (or any other reflection related operation). Turns out that one of the feature that make Scala so interesting (closures) is also a source of incompatibility (the internal anonymous class files that generate are invalid)

So, if for example, I have a code like this (inside any method in a class):

val classNames = Conversions.convertList(names).reduceLeft[String] { (acc, n) =>
acc + ", " + n
}


That generates an inner class that makes Java reflection unusable:



java.lang.IncompatibleClassChangeError: com.googlecode.solder.dwr.WeldContainer and com.googlecode.solder.dwr.WeldContainer$$anonfun$getClasses$1 disagree on InnerClasses attribute
at java.lang.Class.getDeclaringClass(Native Method)
at java.lang.Class.getEnclosingClass(Class.java:1085)
at java.lang.Class.getSimpleBinaryName(Class.java:1220)
at java.lang.Class.getSimpleName(Class.java:1112)
at org.jboss.weld.util.Names.typeToString(Names.java:251)
at org.jboss.weld.util.Names.classToString(Names.java:263)
at org.jboss.weld.introspector.jlr.WeldClassImpl.<init>(WeldClassImpl.java:151)
at org.jboss.weld.introspector.jlr.WeldClassImpl.of(WeldClassImpl.java:133)
at org.jboss.weld.resources.ClassTransformer$2.call(ClassTransformer.java:72)
at org.jboss.weld.resources.ClassTransformer$2.call(ClassTransformer.java:68)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at org.jboss.weld.util.collections.ConcurrentCache.putIfAbsent(ConcurrentCache.java:125)
at org.jboss.weld.resources.ClassTransformer.loadClass(ClassTransformer.java:67)
at org.jboss.weld.bootstrap.BeanDeployer.addClass(BeanDeployer.java:59)
at org.jboss.weld.bootstrap.BeanDeployer.addClasses(BeanDeployer.java:86)
at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:134)
at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:367)
at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:158)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)


Apparently this is a known problem since 2008-08-03 (16 months so far) and AFAIK they are not in a hurry to fix it.



I guess that means I am going to have to start removing Scala from my Weld project. I am sad about this because Scala is IMO a really beautiful language, that feels much cleaner than Java, but if the .class files that it generates are not compatible with the rest of Java... it is just useless for me.

No comments: