In my quest to make Scala blend with JSF and JPA, I’ve been trying to get an app working where I interact with the database while using Scala entities. Obviously, as a first step, I got a simple JPA project working, where my User class looked like:
import java.io.Serializable; import javax.persistence.*; @Entity @Table(name = "user") @NamedQueries({@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"), @NamedQuery(name = "User.findById", query = "SELECT u FROM User u WHERE u.id = :id"), @NamedQuery(name = "User.findByFirstname", query = "SELECT u FROM User u WHERE u.firstname = :firstname"), @NamedQuery(name = "User.findByLastname", query = "SELECT u FROM User u WHERE u.lastname = :lastname")}) public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @Basic(optional = false) @Column(name = "ID") private Integer id; @Column(name = "FIRSTNAME") private String firstname; @Column(name = "LASTNAME") private String lastname; public User() { } public User(Integer id) { this.id = id; } public User(Integer id, String firstname, String lastname) { this.id = id; this.firstname= firstname; this.lastname = lastname; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } }
So once I got this to work, my next step was to write the same thing in Scala, I wrote it like:
import scala.reflect._ import javax.persistence._ @Entity class User(@Id @Column{val name="ID"} @BeanProperty val id:Integer, @Column{val name="firstname"} @BeanProperty val firstname: String, @Column{val name="lastname"} @BeanProperty val lastname:String) { }
To make this work from my Java code, I made sure I pointed to my scala User class instead of Java, this includes the persistence.xml file as well. When I tried to run this, I got the following error:
Exception [EclipseLink-0] (Eclipse Persistence Services – 1.0.1 (Build 20080905) ): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions:
Exception [EclipseLink-63] (Eclipse Persistence Services – 1.0.1 (Build 20080905 )): org.eclipse.persistence.exceptions.DescriptorException Exception Description:
The instance creation method [scalajpa.User.], with no parameters, does not exist, or is not accessible.
Internal Exception: java.lang.NoSuchMethodException: scalajpa.User.() Descriptor: RelationalDescriptor(scalajpa.User –> [DatabaseTable(USER)])
So I realised I needed a default constructor for my User method, so I changed my scala class to:
import scala.reflect._ import javax.persistence._ @Entity class User { @Id @Column{val name="ID"} @BeanProperty var id:Integer= _ @Column{val name="firstname"} @BeanProperty var firstname: String = _ @Column{val name="lastname"} @BeanProperty var lastname:String = _ }
This worked out perfect. Talk about missing the obvious :-). I realised I had to make this change when I looked here.
While I really like the compactness I got out of it, I’m not too thrilled about having to create a new Scala project, where I need all the EclipseLink libraries on the classpath, then build the Scala project into a jar and put it on the classpath of the JPA application. The whole process would be much easier if I could just create a Scala class right inside my JPA application and have it accessible from other java classes. I tried this and unfortunately the java classes did not recognize the Scala class :(.
As a next step, I plan to get a JSF + JPA application working with whatever help they can get from Scala.
Hi Vikas,
I’ve added a link to your blog from the EclipseLink wiki (http://wiki.eclipse.org/EclipseLink/Articles). Feel free to add links on the wiki to any other blogs you might write about EclipseLink and Scala.
If you’re interested, we have the perfect place for you to further explain how to use Scala with EclipseLink (http://wiki.eclipse.org/EclipseLink/Examples/JPA)!
–Shaun
Out of curiosity, why use @BeanProperty in combination with field access JPA annotations?
The @BeanProperty is a part of the scala.reflect package and it generates getter and setter methods for the field.
I realize what they do but I don’t see the need… from http://www.hars.de/2009/03/jpa-with-scala.html
“The first version contained @BeanProperty annotations on all fields, which are nice in general, but unnecessary for JPA.”
I would like to map an Enum with eclipselink. I saw examples how I’m able to do this with hibernate. Can anybody give me a hint ?
TIA
Martin
maybe this http://github.com/FaKod/JPA-for-Scala has some useful ideas as well…