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.

Monday, November 16, 2009

Playing with Weld and Scala to create a new framework for JSPs

Today I built my first "serious" example using Weld and Scala.
You can take a look at it in here.
So far, Weld looks like really good framework, I am still not able to say that it will replace Spring as my "glue framework", but that could certainly become true.
Scala also looks interesting (this also my first "serious" attempt at doing something with Scala), but the support for Scala in Eclipse is very fragile... the plug-in still needs a lot of polishing (no refatoring, no quickfixes, and the syntax coloring and cursor control sometimes goes crazy). I would not recommend the Scala plugin in Eclipse for "real work", but for hobbing is fine. (I wonder if the support for Scala in the Netbeans or the opensourced version of IntelliJ is better).

Friday, November 06, 2009

JPA Myth: EclipseLink and Hibernate are compatible. Not true: Hibernate does NOT follow the JPA Spec

Please take a look at the Hibernate JIRA issue EJB-441, seen it?

Now, please tell me if this is correct:

According to Gavin King (author of Hibernate) the JPA spec the @Column(nullable=false) is just a schema generation hint, and therefore JPA implementations should NOT use it for object level validation.

I think that means that if an entity object with a null property marked with the @Column(nullable=false) is persisted using entityManager.persist() it should crash with a java.sql.SQLException as the root exception, thrown when the "INSERT" statement failed after it was sent to the database by the JDBC driver (as it happens in EclipseLink), and not because some implementation specific mechanism "pre-validated" it and prevented it from reaching the database (as it happens in Hibernate thanks to org.hibernate.engine.Nullability.checkNullability).

Is that correct? Because I don’t know anymore!

Lets say that is correct, does that means that the following is correct too?:

Validation should be entirely the responsibility of the JSR-303, and the properties of an entity should only be checked for nullability before sending to the database if a JSR-303 implementation is there to indicate that.

Is that true? And if it is, then:

What is exactly the difference between @Basic(optional=true) and @Column(nullable=true)? What happens when this 2 are applied to the same property, but they contradict each other? (As in : @Basic(optional=false) and @Column(nullable=true) or in @Basic(optional=true) and @Column(nullable=false)

I could not find a statisfactory answer in the spec documentation, would anyone be so kind as to resolve this issue? Because it Hibernate Forums they have decided that the way to deal with this inconsistencies and contradictions in Hibernate and in the JPA standard is to plain ignore me since May of 2009.

As you can see I tried to raise the issue with 2 JIRAS, forum post and easy to reproduce unit-tests, but nothing seems to work… what should I do then?