Zakładamy, że utworzony programowo dokument został zapisany w postaci pliku HTML. Co jednak, gdybyśmy chcieli mieć możliwość zapisu i późniejszego odczytu zawartości dokumentu?
Jednym z wygodnych rozwiązań jest zastosowanie JAXB (Java Architecture for XML Binding), biblioteki pozwalającej na zapis złożonej struktury obiektów w pamięci w formacie XML (ang. marshal) i późniejsze odtworzenie struktury obiektów z dokumentu XML (ang. unmarshal).
Aby zapis i odczyt był mozliwy musi być spełnionych kilka warunków:
Dla przypomnienia <to:jest:tag att=“a to jest atrybut”>
a tag zamykający wygląda tak </to:jest:tag>
.
Biblioteka JAXB używa specyficznego mechanizmu języka - adnotacji (ang. annotations) [który chyba nie będzie omawiany na wykładzie ???]
Adnotacje mają postać @Identifier
lub @Identifier(key=value[,otherkey=othervalue])
i są umieszczane w kodzie programu, zazwyczaj przed definicją klasy, deklaracją atrybutu lub definicją metody.
Na przykład:
<code java>
@Override public String toString(){ return ""; }
</code>
Adnotacje nie mają bezpośredniego wpływu na wykonanie kodu, ale mogą być wykorzystywane przez zewnętrzne narzędzia przetwarzające kod (zarówno źródłowy, jak i skompilowany):
@org.junit.Test
Formalnie, adnotacje deklaruje się jak interfejsy i umieszcza w pakietach
Dodając adnotacje zadbaj, aby importować elementy z pakietu javax.xml.bind.annotation
Dodaj w klasie Document
metody do zapisu i odczytu
<code java>
public void write(String fileName){ try { JAXBContext jc = JAXBContext.newInstance(Document.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); FileWriter writer= new FileWriter(fileName);; m.marshal(this, writer); } catch (JAXBException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } public static Document read(String fileName){ try { JAXBContext jc = JAXBContext.newInstance(Document.class); Unmarshaller m = jc.createUnmarshaller(); FileReader reader = new FileReader(fileName); return (Document) m.unmarshal(reader); } catch (JAXBException ex) { ex.printStackTrace(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } return null; }
</code>
Dodaj także w funkcji main()
kod, który zapisuje (i odczytuje) dokument
<code java>
cv.write("cv.xml"); //Document cv2 = Document.read("cv.xml"); //cv2.writeHTML(System.out);
</code>
Java SE 9 nie widzi części modułów Java EE, w tym JAXB.
1. W IntelliJ w dialogu Project Structure - ustaw Project language Level : 8 - lambdas, type annotations
2. Zalecanym obejściem (w https://blog.codefx.org/java/java-9-migration-guide/) jest dodanie opcji uruchamiania programu
<code> –add-modules java.se.ee </code>
W IntelliJ nalezy je wpisac w oknie Run → Edit Configurations → pole VM options
W następnych etapach będziemy modyfikowali kod (dodawali adnotacje) i sprawdzali, co zmienia się w pliku cv.xml
Najczęściej używane będą następujące adnotacje
@XmlRootElement
- oznaczenie klasy będącej korzeniem drzewa XML @XmlElement
- oznaczenie, że atrybut ma zostać zapisany jako element XML (jako nazwa znacznika XML zostanie użyta nazwa atrybutu) @XmlElement(name=“xyz”)
- podana jest nazwa znacznika xyz
XmlAttribute
atrybut (pole klasy) zostanie zapisany jako atrybut XML <code java> @XmlRootElement public class Document { … } </code>
Zobacz, co zostało zapisane do pliku cv.xml
<code java>
@XmlElement String title; @XmlElement List<Section> sections = new ArrayList<>(); @XmlElement Photo photo;
</code>
Wykonaj program i spróbuj zidentyfikować i naprawić błąd…
Pole url
odwzorujemy w atrybut
<code java>
@XmlAttribute String url;
</code>
Tytuł jest zapewne krótki - odwzorujemy go w atrybut, natomiast listę akapitów (paragraphs
) w XmlElement
Zastąp w odpowiednim miejscu @XmlElement
przez @XmlElement(name=“section”)
i @XmlElement(name=“paragraph”)
.
1. Uzupełnijmy więc znaczniki w ParagraphWithList
, UnorderedList oraz ListItem
Prawdopodobnie dalej lista w cv.xml
nie będzie widoczna…
2. Poinformuj, JAXB o klasach potomnych Paragraph
<code java> @XmlSeeAlso({ParagraphWithList.class}) public class Paragraph { </code>
… i usuń ewentualne błędy.
3. Możesz przyjrzeć się znacznikom i poprawić nazwy według uznania