Last active
August 29, 2015 14:06
-
-
Save caoilte/aa7839935a29713a7a51 to your computer and use it in GitHub Desktop.
Bending JAXB to the will of Scala [1/2]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class EntryType(entrytypeoption: Seq[scalaxb.DataRecord[Any]] = Nil, | |
attributes: Map[String, scalaxb.DataRecord[Any]]) extends FeedTypeOption | |
case class EntryType(entrytypeoption: Seq[scalaxb.DataRecord[Any]] = Nil, | |
xmlbase: Option[java.net.URI] = None, | |
xmllang: Option[String] = None, | |
attributes: Map[String, scalaxb.DataRecord[Any]]) extends FeedTypeOption |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
java.lang.NullPointerException | |
at com.sun.xml.internal.bind.v2.runtime.output.Encoded.setEscape(Encoded.java:96) | |
at com.sun.xml.internal.bind.v2.runtime.output.UTF8XmlOutput.doText(UTF8XmlOutput.java:306) | |
at com.sun.xml.internal.bind.v2.runtime.output.UTF8XmlOutput.text(UTF8XmlOutput.java:290) | |
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.leafElement(XMLSerializer.java:314) | |
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$StringImplImpl.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:1037) | |
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$StringImplImpl.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:1016) | |
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:241) | |
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:114) | |
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343) | |
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582) | |
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:325) | |
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483) | |
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) | |
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) | |
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.target.field | |
import javax.xml.bind.annotation._ | |
import javax.xml.bind.annotation.adapters._ | |
type xmlElement = XmlElement @field | |
type xmlTypeAdapter = XmlJavaTypeAdapter @field | |
class OptionAdapter[A](nones: A*) extends XmlAdapter[A, Option[A]] { | |
def marshal(v: Option[A]): A = v.getOrElse(nones(0)) | |
def unmarshal(v: A) = if (nones contains v) None else Some(v) | |
} | |
object Email { | |
class EmailOptionAdapter extends OptionAdapter[Email](null, Email("")) | |
} | |
@XmlAccessorType(XmlAccessType.FIELD) | |
case class Email(@xmlValue email:String) { | |
override def toString = email | |
private def this() = this("") | |
} | |
@XmlRootElement | |
@XmlAccessorType(XmlAccessType.FIELD) | |
case class Person(name:String, | |
@xmlTypeAdapter(classOf[Email.EmailOptionAdapter]) email:Option[Email] = None) { | |
private def this() = this("", None) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
java.lang.NullPointerException | |
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:54) | |
at sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38) | |
at java.lang.reflect.Field.get(Field.java:379) | |
at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.get(Accessor.java:266) | |
at com.sun.xml.bind.v2.runtime.reflect.Accessor.getUnadapted(Accessor.java:143) | |
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.hasValue(TransducedAccessor.java:251) | |
at com.sun.xml.bind.v2.model.impl.RuntimeClassInfoImpl$TransducerImpl.writeLeafElement(RuntimeClassInfoImpl.java:409) | |
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:256) | |
at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:130) | |
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361) | |
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593) | |
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:342) | |
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494) | |
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323) | |
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:251) | |
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.target.field | |
import javax.xml.bind.annotation._ | |
import javax.xml.bind.annotation.adapters._ | |
import org.joda.time.DateTime | |
import org.joda.time.format.DateTimeFormatter | |
type xmlElement = XmlElement @field | |
type xmlTypeAdapter = XmlJavaTypeAdapter @field | |
/** | |
* NB The double type parameters ([S,A]) are necessary because MOXy always uses the first one as a target for casting | |
* from the input string before passing to unmarshal. Unfortunately this means you need to always pass String as | |
* the first type parameter when extending the CustomOptionAdapter (eg see DateTimeOptionAdapter). | |
* | |
* These bugs describe the behaviour and fix, | |
* - https://bugs.eclipse.org/bugs/show_bug.cgi?id=440681 | |
* - https://bugs.eclipse.org/bugs/show_bug.cgi?id=431803 | |
* The fix should be available in the next release after 2.5.2 | |
*/ | |
class CustomOptionAdapter[S,A](customAdapter:XmlAdapter[String,A], nones: String*) extends XmlAdapter[String, Option[A]] { | |
def marshal(v: Option[A]): String = { | |
v.map(customAdapter.marshal).getOrElse(nones(0)) | |
} | |
def unmarshal(v: String):Option[A] = { | |
if (nones contains v) None else Some(customAdapter.unmarshal(v)) | |
} | |
} | |
class DateTimeAdapter(dtf: DateTimeFormatter) extends XmlAdapter[String, DateTime] { | |
def unmarshal(v: String): DateTime = dtf.parseDateTime(v) | |
def marshal(v: DateTime): String = dtf.print(v) | |
} | |
class DateTimeOptionAdapter(dtf: DateTimeFormatter) extends CustomOptionAdapter[String, DateTime](new DateTimeAdapter(dtf), null, "") | |
@XmlRootElement | |
@XmlAccessorType(XmlAccessType.FIELD) | |
case class Entry(id:String | |
@xmlTypeAdapter(classOf[AtomDateTimeOptionAdapter]) published:Option[DateTime] = None { | |
private def this() = this("", None) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment