I have a save command that does simple marshalling:
//save command
...
try {
JAXBContext context = JAXBContext.newInstance(CollectionManager.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(collectionManager, new File("out.xml"));
} catch (JAXBException e) {
e.printStackTrace();
}
...
here is collectionManager with PrioriyQueue storing MusicBands
@XmlRootElement(name = "Collection")
@XmlAccessorType(XmlAccessType.FIELD)
public class CollectionManager {
...
@XmlElement(name = "MusicBand")
private PriorityQueue<MusicBand> musicBandsQueue;
...
here are MusicBand class fields:
@XmlType(propOrder = {"id","name","coordinates", "numberOfParticipants", "creationDate", "albumsCount", "establishmentDate", "genre", "label"})
public class MusicBand implements Comparable<MusicBand> {
private long id;
private String name;
private Coordinates coordinates;
private java.util.Date creationDate;
private int numberOfParticipants;
private Long albumsCount;
private java.time.ZonedDateTime establishmentDate;
private MusicGenre genre;
private Label label;
...
So, when I exclude "creationDate" from propOrder, I almost get the desired xml file except the "establishmentDate" field. idk what happens to it.
here's how it looks.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Collection>
<MusicBand>
<id>1</id>
<name>asd</name>
<coordinates>
<x>1</x>
<y>1</y>
</coordinates>
<numberOfParticipants>1</numberOfParticipants>
<albumsCount>1</albumsCount>
<establishmentDate/>
<genre>SOUL</genre>
<label>
<bands>2</bands>
<name>asd</name>
</label>
</MusicBand>
<previousIds>1</previousIds>
</Collection>
But after if I include "creationDate" in propOrder, I get an exception. Here is the stack trace:
org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Property creationDate appears in @XmlType.propOrder, but no such property exists. Maybe you meant coordinates?
this problem is related to the following location:
at ru.itmo.prog.lab5.collection.MusicBand.MusicBand
at private java.util.PriorityQueue ru.itmo.prog.lab5.CLI.Managers.CollectionManager.musicBandsQueue
at ru.itmo.prog.lab5.CLI.Managers.CollectionManager
at org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:83)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:421)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:255)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1115)
at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:144)
at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:44)
at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:373)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:605)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:546)
at ru.itmo.prog.lab5.CLI.Commands.Save.execute(Save.java:22)
at ru.itmo.prog.lab5.CLI.Managers.CommandManager.executeCommand(CommandManager.java:58)
at ru.itmo.prog.lab5.Main.main(Main.java:19)
Don't have any ideas as to why that could be a problem. date marshalling works fine in baeldung's jaxb guide. Any help would be appreciated.
In order to solve the problem, i reached out to the next problems on StackOverflow (it's worth reading all of them if you have similar issue to me): first, second. So in one of the comments i found an open-source library threeten-jaxb, which helps with @JavaTypeAdapter
annotations.
In my case, i needed a class for ZonedDateTime field, which i found there, it's called ZonedDateTimeXmlAdapter
. As for the java.util.Date
field, i just created my personal DateAdapter class as described in the first problem i mentioned above.
Important note: i had to put annotations above getters, not the actual fields, otherwise i would get an exception that there are 2 or more properties named the same way. Didn't actually figure out as to why it is so, but rather just tried different ways of putting annotations in different places...
The only little drawback that's left because of a custom DateAdapter class is that I lose a town in date tag in xml, but in my case it's not so important. Here's what i have in collection: created: Thu Mar 14 12:35:50 MSK 2024
and here's what i get in xml:<creationDate>2024-03-14 12:35:50</creationDate>
Didn't find a proper class in threeten library to fix this.
upd: managed to fix the annotations problem (turned out i had a lack of jaxb package knowledge) so, in order to work properly, i put annotations like this in two classes, my collection:
@XmlType(propOrder = { "id", "name", "coordinates", "numberOfParticipants", "creationDate", "albumsCount",
"establishmentDate", "genre", "label" })
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MusicBand implements Comparable<MusicBand> {
@XmlAttribute
private long id;
@XmlElement(required = true)
private String name;
@XmlElement(required = true)
private Coordinates coordinates;
@XmlElement(required = true)
private java.util.Date creationDate;
@XmlElement(required = true)
private int numberOfParticipants;
@XmlElement
private Long albumsCount;
@XmlElement
@XmlJavaTypeAdapter(ZonedDateTimeXmlAdapter.class)
private java.time.ZonedDateTime establishmentDate;
@XmlElement(required = true)
private MusicGenre genre;
@XmlElement(required = true)
private Label label;
//setters getters etc
my collection manager:
@XmlRootElement(name = "MusicBandCollection")
@XmlAccessorType(XmlAccessType.FIELD)
public class CollectionManager {
@XmlElement(name = "musicBand")
@XmlElementWrapper(name = "musicBands")
private PriorityQueue<MusicBand> musicBandsQueue;
private final static LocalDateTime InitilizationDate = LocalDateTime.now();
@XmlTransient
private ArrayList<Long> previousIds = new ArrayList<Long>();
//setters getters etc