In the "code club" / "dojo" or whatever you want to call it that Ben (aka Johnny Coder) organized we have been learning about Scala the last few weeks. I have been puttering with Scala on my own for about a year now, and it has been fun to engage with other folk in the learning process. We have mostly been doing a mix of Project Euler and the S-99 problems as exercises. Those problems are fun, but they don’t really reflect the kind of day to day programming tasks that I am usually engaged in.

To scratch that slightly more practical itch, I decided to see how well Scala fits in with other tools in the Java ecosystem. The Java ecosystem being broad, and my Scala kung fu being not that strong, all I have are some possibly interesting bits I discovered while trying to get Scala and RESTEasy working together.  I picked RESTEasy because in the middle of reading RESTful Java with JAX-RS.

I started off with an existing example project from chapter 11 in the RESTEasy book. I added the Scala plugin to the maven build, and I was off.

The first class I converted over was a JAXB annotated class com.restfully.shop.domain.Customer

I ran into a few things that caused me problems.  The first was this compiler message:

"';' expected but ',' found"


At the @XMLType annotation line.  The resolution was to switch from using the Array literal "{}" Java syntax to the Scala Array object.



I also got a JAXB runtime error during the JUnit tests:



....
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 15 counts of IllegalAnnotationExceptions
There are two properties named ....


I resolved that by using the @XmlAccessorType(XmlAccessType.FIELD) annotation.



For compatibility with the existing code that expected Java Bean style property access, I added the @BeanProperty annotation.   The annotation causes Scala to automatically generate get/set methods.



Here is the java version of Customer:



package com.restfully.shop.domain;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name = "customer")
@XmlType(propOrder = {"firstName", "lastName", "street", "city", "state", "zip", "country"})
public class Customer
{
private int id;
private String firstName;
private String lastName;
private String street;
private String city;
private String state;
private String zip;
private String country;

@XmlAttribute
public int getId()
{
return id;
}

public void setId(int id)
{
this.id = id;
}

@XmlElement(name = "first-name")
public String getFirstName()
{
return firstName;
}

public void setFirstName(String firstName)
{
this.firstName = firstName;
}

@XmlElement(name = "last-name")
public String getLastName()
{
return lastName;
}

public void setLastName(String lastName)
{
this.lastName = lastName;
}

@XmlElement
public String getStreet()
{
return street;
}

public void setStreet(String street)
{
this.street = street;
}

@XmlElement
public String getCity()
{
return city;
}

public void setCity(String city)
{
this.city = city;
}

@XmlElement
public String getState()
{
return state;
}

public void setState(String state)
{
this.state = state;
}

@XmlElement
public String getZip()
{
return zip;
}

public void setZip(String zip)
{
this.zip = zip;
}

@XmlElement
public String getCountry()
{
return country;
}

public void setCountry(String country)
{
this.country = country;
}

@Override
public String toString()
{
return "Customer{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", street='" + street + '\'' +
", city='" + city + '\'' +
", state='" + state + '\'' +
", zip='" + zip + '\'' +
", country='" + country + '\'' +
'}';
}
}


Here is my Scala conversion of Customer:



package com.restfully.shop.domain

import javax.xml.bind.annotation.XmlAttribute
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
import javax.xml.bind.annotation.XmlType
import javax.xml.bind.annotation.XmlAccessorType
import javax.xml.bind.annotation.XmlAccessType

import scala.reflect.BeanProperty

@XmlRootElement(name = "customer")
@XmlType(propOrder = Array("firstName", "lastName", "street", "city", "state", "zip", "country"))
@XmlAccessorType(XmlAccessType.FIELD)
class Customer {

@XmlAttribute
@BeanProperty
var id: Int = _

@XmlElement(name = "first-name")
@BeanProperty
var firstName: String = _

@XmlElement(name = "last-name")
@BeanProperty
var lastName: String = _

@XmlElement
@BeanProperty
var street: String = _

@XmlElement
@BeanProperty
var city: String = _

@XmlElement
@BeanProperty
var state: String = _

@XmlElement
@BeanProperty
var zip: String = _

@XmlElement
@BeanProperty
var country: String = _

override def toString =
"Customer{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", street='" + street + '\'' +
", city='" + city + '\'' +
", state='" + state + '\'' +
", zip='" + zip + '\'' +
", country='" + country + '\'' +
'}'

}


The next class I converted was com.restfully.shop.domain.Customers



This conversion was very similar, but it was dealing with collections.  I found that Scala 2.8 has a new object scala.collection.JavaConversions that contains many implicit conversion for Java collections. 



Here is the Java version of Customers:



package com.restfully.shop.domain;

import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
* @author Bill Burke
* @version $Revision: 1 $
*/
@XmlRootElement(name = "customers")
public class Customers
{
protected Collection customers = new ArrayList();
protected List links;

@XmlElementRef
public Collection getCustomers()
{
return customers;
}

public void setCustomers(Collection customers)
{
this.customers = customers;
}

@XmlElementRef
public List getLinks()
{
return links;
}

public void setLinks(List links)
{
this.links = links;
}

@XmlTransient
public String getNext()
{
if (links == null) return null;
for (Link link : links)
{
if ("next".equals(link.getRelationship())) return link.getHref();
}
return null;
}

@XmlTransient
public String getPrevious()
{
if (links == null) return null;
for (Link link : links)
{
if ("previous".equals(link.getRelationship())) return link.getHref();
}
return null;
}

}


Here is my Scala conversion of Customers:



package com.restfully.shop.domain

import java.util.{ArrayList => JArrayList}
import java.util.{Collection => JCollection}
import java.util.{List => JList}

import javax.xml.bind.annotation.XmlElementRef
import javax.xml.bind.annotation.XmlRootElement
import javax.xml.bind.annotation.XmlTransient
import javax.xml.bind.annotation.XmlAccessorType
import javax.xml.bind.annotation.XmlAccessType

import scala.collection.Iterable
import scala.collection.JavaConversions._
import scala.collection.mutable.Buffer

@XmlRootElement(name = "customers")
@XmlAccessorType(XmlAccessType.PROPERTY)
class Customers {

var customers = Iterable[Customer]()
var links: Buffer[Link] = Buffer()

@XmlElementRef
def getCustomers: JCollection[Customer] = customers
def setCustomers(customers: JCollection[Customer]) = {
this.customers = customers
}

@XmlElementRef
def getLinks: JList[Link] = links
def setLinks(links: JList[Link]) = {
this.links = links
}

@XmlTransient
def getNext(): String = findHref("next")

@XmlTransient
def getPrevious(): String = findHref("previous")

private def findHref(rname: String): String = {
val rel = links.filter(_.getRelationship == rname)
rel match {
case Buffer() => null
case _ => rel.head.getHref
}
}

}


That’s about as far as I got this weekend.  I guess I was actually mostly working with JAXB this time.  The same example code has JPA as was as JAX-RS, and I’m going to try and convert the entire project to Scala, and if I do, I’ll upload it to BitBucket.