2010-03-25 7 views
60

Ich kann JAXB nicht abmelden einen Zeitstempel in einer Rasteasy JAX-RS-Server-Anwendung.jaxb unmarshal timestamp

sieht Meine Klasse wie folgt:

@XmlAccessorType(XmlAccessType.NONE) 
@XmlRootElement(name = "foo") 
public final class Foo { 
    // Other fields omitted 

    @XmlElement(name = "timestamp", required = true) 
    protected Date timestamp; 

    public Foo() {} 

    public Date getTimestamp() { 
     return timestamp; 
    } 

    public String getTimestampAsString() { 
     return (timestamp != null) ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp) : null; 
    } 

    public void setTimestamp(final Date timestamp) { 
     this.timestamp = timestamp; 
    } 

    public void setTimestamp(final String timestampAsString) { 
     try { 
      this.timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timestampAsString); 
     } catch (ParseException ex) { 
      this.timestamp = null; 
     } 
    } 
} 

Irgendwelche Ideen?

Danke.

Antwort

106

JAXB kann die Klasse java.util.Date verarbeiten. Allerdings erwartet sie das Format:

"yyyy-MM-dd'T'HH: mm: ss" statt "yyyy-MM-dd HH: mm: ss"

Wenn Sie dieses Datum verwenden, Format ich würde mit einem XMLAdapter vorschlagen, würde es so etwas wie folgt aussehen:

import java.text.SimpleDateFormat; 
import java.util.Date; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class DateAdapter extends XmlAdapter<String, Date> { 

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 

    @Override 
    public String marshal(Date v) throws Exception { 
     return dateFormat.format(v); 
    } 

    @Override 
    public Date unmarshal(String v) throws Exception { 
     return dateFormat.parse(v); 
    } 

} 

Sie würden dann diesen Adapter auf Ihrer Zeitstempel-Eigenschaft angeben:

import java.util.Date; 

import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlAccessorType(XmlAccessType.NONE) 
@XmlRootElement(name = "foo") 
public final class Foo { 
    // Other fields omitted 

    @XmlElement(name = "timestamp", required = true) 
    @XmlJavaTypeAdapter(DateAdapter.class) 
    protected Date timestamp; 

    public Foo() {} 

    public Date getTimestamp() { 
     return timestamp; 
    } 

    public void setTimestamp(final Date timestamp) { 
     this.timestamp = timestamp; 
    } 

} 
+1

Ich habe tatsächlich herausgefunden, wie Sie die Übersetzung mit @ XmlJavaTypeAdapter tun. Dadurch konnte ich verschiedene Java-Klassen, die in meinem Code eine spezielle Behandlung erforderten, anpassen. Vielen Dank. – Ralph

+5

Sie müssen sehr vorsichtig mit SimpleDateformat sein, da es nicht threadsicher ist! Ich bin mir nicht sicher, ob JAXB jedes Mal ein neues Objekt für den Adapter erstellt. –

+0

Weitere Informationen finden Sie unter: http://bdoughan.blogspot.com/2011/01/jaxb-and-datetime-properties.html –

10

JAXB kann Date Objekte nicht direkt marshalieren, weil sie nicht genügend Informationen haben, um eindeutig zu sein. JAXB hat die Klasse XmlGregorianCalendar für diesen Zweck eingeführt, aber es ist sehr unangenehm, direkt zu verwenden.

Ich schlage vor, Ihr timestamp Feld zu einem XmlGregorianCalendar zu ändern, und ändern Sie Ihre verschiedenen Methoden, um dieses Feld zu aktualisieren, während Sie die öffentliche Schnittstelle behalten, die Sie bereits haben, wenn möglich.

Wenn Sie das Date Feld behalten wollen, dann müssen Sie Ihre eigene XmlAdapter Klasse implementieren JAXB zu sagen, wie Sie Ihre Date zu und von XML einzuschalten.

+2

JAXB kann java.util.Date sicher marshalen, nur das Format ist "JJJJ-MM-TTTHH: mm: ss" passend zu xsd: dateTime. Die EclipseLink JAXB-Implementierung (MOXy) kann auch die java.sql.Date/Time/Timestamp-Typen verarbeiten. –

+2

@Blaise: Ich stehe korrigierte – skaffman

3

um das XML-Einweiser zu erhalten zu generieren ein xsd: datum f ormatted als YYYY-MM-DD, ohne eine XMLAdapter definiert ich diese Methode verwendet, um eine Instanz von javax.xml.datatype.XMLGregorianCalendar zu bauen:

public XMLGregorianCalendar buildXmlDate(Date date) throws DatatypeConfigurationException { 
    return date==null ? null : DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(date)); 
} 

Mit dem Ergebnis, initialisiert das I XMLGregorianCalendar Feld der durch JAXB Compiler generierten Klasse (in Eclipse):

Date now = new Date(); 
    ... 
    report.setMYDATE(buildXmlDateTime(now)); 
    ... 
    JAXBContext context = JAXBContext.newInstance(ReportType.class); 
    Marshaller m = context.createMarshaller(); 
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
    m.marshal(new ObjectFactory().createREPORT(report), writer); 

und erhalten den Tag formatiert wie erwartet:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<REPORT> 
    ... 
    <MY_DATE>2014-04-30</MY_DATE> 
    ... 
</REPORT> 
3

dieses Adapters sollte Thread-sicher sein:

public class DateXmlAdapter extends XmlAdapter<String, Date> { 

    /** 
    * Thread safe {@link DateFormat}. 
    */ 
    private static final ThreadLocal<DateFormat> DATE_FORMAT_TL = new ThreadLocal<DateFormat>() { 

     @Override 
     protected DateFormat initialValue() { 
      return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 
     } 

    }; 

    @Override 
    public Date unmarshal(String v) throws Exception { 
     return DATE_FORMAT_TL.get().parse(v); 
    } 

    @Override 
    public String marshal(Date v) throws Exception { 
     return DATE_FORMAT_TL.get().format(v); 
    } 

} 
+0

Ich habe den folgenden Fehler erhalten: org.xml.sax.SAXParseException ; Zeilennummer: 0; Spaltennummer: 0; cvc-datatype-valid.1.2.1: '05/10/2017 00:00:00 'ist kein gültiger Wert für' dateTime ' – Aguid

+0

Ihre Zeichenfolge '05/10/2017 00:00:00' hat nicht das Format erwartet: "JJJJ-MM-TT'T'HH: mm: ss" - Sie sollten entweder Eingabe oder Format ändern – dermoritz

+0

INFRAXML 2.2: javax.xml.bind.MarshalException - mit verknüpfter Ausnahme: [org.xml.sax. SAXParseException; Zeilennummer: 0; Spaltennummer: 0; cvc-datatype-valid.1.2.1: '2017-10-10T14: 59: 34' ist kein gültiger Wert für 'Datum'.] – Aguid

Verwandte Themen