Am observat anumite formate de dată și timp care nu pot fi citite corecte cu api-ul JAXB din Java. Mai bine spus, nu pot fi citite, adică acel câmp mapat în clasa din aplicație este null.
Un exemplu de format de dată și timp cu timezone ar fi acesta 2020-10-13T12:25:00+0200.
In aplicație, campul aferent timestamp-ului are ca tip de data XMLGregorianCalendar
, o clasă destul de veche folosită pentru a reprezenta timestamp-uri. Clasă veche și un format de timp mai deosebit din punct de vedere al timezone-ului nu fac casă bună și când am pornit testul pentru a vedea dacă se poate citi acel fișier, a ieșit o foarte frumoasă exceție NullPointerException.
Soluția cea mai la îndemană a fost să înlocuiesc XMLGregorianCalendar
cu String
și astfel citirea se face corect, eventualele erori, cum ar fi lipsa timestamp-ului sau invaliditatea lui, rămânând de tratat la un nivel mai sus, al aplicației.
O altă soluție ar mai fi screrea unui XmlAdapter custom care poate fi folosit pentru a citi corect acel câmp de dată din fișier.
Un exemplu, în cazul problemei de față ar fi acesta:
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
package com.mycompany.app; | |
import javax.xml.bind.ValidationEventHandler; | |
import javax.xml.bind.annotation.adapters.XmlAdapter; | |
import javax.xml.datatype.DatatypeFactory; | |
import javax.xml.datatype.XMLGregorianCalendar; | |
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
import java.util.GregorianCalendar; | |
public class DateTimeAdapter extends XmlAdapter<String, XMLGregorianCalendar> { | |
/** | |
* Convert a value type to a bound type. | |
* | |
* @param v The value to be converted. Can be null. | |
* @throws Exception if there's an error during the conversion. The caller is responsible for | |
* reporting the error to the user through {@link ValidationEventHandler}. | |
*/ | |
@Override | |
public XMLGregorianCalendar unmarshal(String v) throws Exception { | |
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse(v); | |
GregorianCalendar c = new GregorianCalendar(); | |
c.setTime(date); | |
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); | |
return date2; | |
} | |
/** | |
* Convert a bound type to a value type. | |
* | |
* @param v The value to be convereted. Can be null. | |
* @throws Exception if there's an error during the conversion. The caller is responsible for | |
* reporting the error to the user through {@link ValidationEventHandler}. | |
*/ | |
@Override | |
public String marshal(XMLGregorianCalendar v) throws Exception { | |
return null; | |
} | |
} |
Și se folosește ca adnotare pe campul respectiv din clasă
@XmlJavaTypeAdapter(DateTimeAdapter.class) protected XMLGregorianCalendar timestamp;