Shadowman
Shadowman

Reputation: 12059

Quarkus - JAXB with OffsetDateTime?

I'm trying to deserialize an XML String to a Java Object using Quarkus 3.15 and JAXB. My Java Object has a property with type OffsetDateTime, but when I try to deserialize it I get the following error:

No default constructor found on class java.time.OffsetDateTime: java.lang.NoSuchMethodException: java.time.OffsetDateTime.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3585)
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
    at org.glassfish.jaxb.core.v2.ClassFactory.tryGetDeclaredConstructor(ClassFactory.java:109)
    at org.glassfish.jaxb.core.v2.ClassFactory.create0(ClassFactory.java:78)
    at org.glassfish.jaxb.runtime.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:255)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:655)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:156)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:530)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:509)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:518)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:183)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:351)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2726)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:542)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:889)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:825)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1224)
    at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:637)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:218)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:189)
    at jakarta.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:152)
    at jakarta.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:205)

My Java Object looks something like this:

@XmlRootElement(name="MyXmlPojo")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyXmlPojo {

    @XmlElement
    private String propA = null;

    @XmlElement
    private String propB = null;

    @XmlElement
    private OffsetDateTime dateProp = null;

    <snip>
}

Is there a way to easily support OffsetDateTime in JAXB?

EDIT: Added a sample Pojo with annotations that's similar to what I'm working with

Upvotes: 1

Views: 92

Answers (1)

Laurent Schoelens
Laurent Schoelens

Reputation: 2848

You should add the following annotation to your OffsetDateTime fields :

@XmlJavaTypeAdapter(OffsetDateTimeAdapter.class)

where OffsetDateTimeAdapter would be a class which extends XmlAdapter<String, OffsetDateTime> with following as base code :

public class OffsetDateTimeAdapter extends XmlAdapter<String, OffsetDateTime> {

    @Override
    public OffsetDateTime unmarshal(String inputDate) {
        if (inputDate == null) {
            return null;
        }
        // method logic to get OffsetDateTime from String with appropriate format
        return OffsetDateTime.parse(inputDate);
    }

    @Override
    public String marshal(OffsetDateTime inputDate) {
        if (inputDate == null) {
            return null;
        }
        // method logic to get String from OffsetDateTime with appropriate output format
        return inputDate.toString();
    }
}

EDIT

When generating pojo from XSD, you can add this in binding.xjb

<globalBindings>
    <xjc:javaType name="java.time.OffsetDateTime" xmlType="xs:dateTime" adapter="adapterpkg.OffsetDateTimeAdapter"/>
</globalBindings>

Upvotes: 2

Related Questions