Skip to content

Instantly share code, notes, and snippets.

@caoilte
Last active August 29, 2015 14:06
Show Gist options
  • Save caoilte/d0f1b86cebf68d88a04a to your computer and use it in GitHub Desktop.
Save caoilte/d0f1b86cebf68d88a04a to your computer and use it in GitHub Desktop.
Bending JAXB to the will of Scala [2/2]
import scala.annotation.target.field
import javax.xml.bind.annotation._
import javax.xml.bind.annotation.adapters._
type xmlElement = XmlElement @field
type xmlTypeAdapter = XmlJavaTypeAdapter @field
/**
* NB As with the CustomOptionAdapter we've had to modify the type signature here,
* https://github.com/krasserm/eventsourcing-example/blob/play-blog/modules/service/src/main/scala/dev/example/eventsourcing/util/Binding.scala
* because of the bug in MOXy requiring that the first type parameter of the List Adapter
* be the same as the first type parameter of XmlAdapter
*/
abstract class AbstractListAdapter[B <: AbstractList[A], A] extends XmlAdapter[B, List[A]] {
import scala.collection.JavaConverters._
def marshal(v: List[A]) = {
if (v == null) {
create(new ArrayList[A])
} else create(v.asJava)
}
def unmarshal(v: B) = {
v.elem.asScala.toList
}
def create(l: JList[A]): B
}
trait AbstractList[A] {
def elem: JList[A]
}
object Person {
import java.util.{List => JList}
class PersonsAdapter extends AbstractListAdapter[PersonItems,Person] {
def create(l: JList[Person]) = new PersonItems(l)
}
@XmlAccessorType(XmlAccessType.FIELD)
case class PersonItems(@xmlElementRef(name = "person") elem: JList[Person]) extends AbstractList[Person] {
def this() = this(null)
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
case class Person(name:String){
private def this() = this("")
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
case class Entry(@xmlElement id:String,
@xmlTypeAdapter(classOf[Person.PersonsAdapter]) authors:List[Person]= List()) {
private def this() = this("", List())
}
java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to java.util.Collection
at org.eclipse.persistence.internal.queries.CollectionContainerPolicy.iteratorFor(CollectionContainerPolicy.java:150)
at org.eclipse.persistence.internal.oxm.XMLCompositeDirectCollectionMappingNodeValue.marshal(XMLCompositeDirectCollectionMappingNodeValue.java:78)
at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:149)
at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:401)
at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:240)
at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:751)
import scala.annotation.target.field
import javax.xml.bind.annotation._
import javax.xml.bind.annotation.adapters._
import scala.collection.mutable
import scala.runtime.ScalaRunTime
type xmlElement = XmlElement @field
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
case class Person(name:String) {
private def this() = this("")
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
case class Entry(id:String, author:Array[Person] = Array[Person]()) {
private def this() = this("", Array[Person]())
def productArity = 2
def productElement(n: Int): Any = n match {
case 0 => id
case 1 => mutable.WrappedArray.make(contributor)
case _ => throw new IndexOutOfBoundsException(n.toString)
}
override def equals(that: Any) = ScalaRunTime._equals(this, that)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment