patternjavaMinor
Simple medical collection/database about patients visits
Viewed 0 times
simplecollectiondatabasemedicalaboutvisitspatients
Problem
I am writing a system for doctors who are regularly visited by patients. The doctor adds each patient's visit to collection/database. The class can save data to an .xml file and restore it. Can you give your feedback about this code?
```
// https://github.com/veitsi/jcrf-noweb
import java.util.ArrayList;
import java.util.Date;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Jcrf {
@XmlElement
Jcrf jcrf;
@XmlElement
ArrayList vst = new ArrayList();
public Jcrf() {
super();
}
public static void main(String[] args) {
Jcrf jcrf = new Jcrf();
jcrf.addTestData();
System.out.println(jcrf.vst);
jcrf.toXml();
jcrf.fromXml();
System.out.println(jcrf.vst);
}
public void toXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void fromXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
jcrf = (Jcrf) jaxbUnmarshaller.unmarshal(file);
vst = jcrf.vst;
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void addTestData() {
vst.add(new Visit(1, 1, 366));
vs
```
// https://github.com/veitsi/jcrf-noweb
import java.util.ArrayList;
import java.util.Date;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Jcrf {
@XmlElement
Jcrf jcrf;
@XmlElement
ArrayList vst = new ArrayList();
public Jcrf() {
super();
}
public static void main(String[] args) {
Jcrf jcrf = new Jcrf();
jcrf.addTestData();
System.out.println(jcrf.vst);
jcrf.toXml();
jcrf.fromXml();
System.out.println(jcrf.vst);
}
public void toXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void fromXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
jcrf = (Jcrf) jaxbUnmarshaller.unmarshal(file);
vst = jcrf.vst;
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void addTestData() {
vst.add(new Visit(1, 1, 366));
vs
Solution
File-systems normally make poor databases because you lose the concept of 'atomicity'... let's take a worst-case example:
What happens if there is an IOException part-way through the
A more traditional way to prevent this sort of loss is to write the output to a new file, and then do an atomic 'move' operation:
Note the use of the atomic Files.move(...)` command.
One day, when your file-system is full, and you run out of space... you will appreciate that change.
public void toXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}What happens if there is an IOException part-way through the
jaxbMarshaller.marshal(this, file); ? You end up overwriting the old copy, and losing the new one. Your data is gone.A more traditional way to prevent this sort of loss is to write the output to a new file, and then do an atomic 'move' operation:
public void toXml() {
try {
File file = new File("jcrf.xml.tmp");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
// move tmp file to complete output file.
Path tmp = file.toPath();
Path target = Paths.get("jcrf.xml");
Files.move(tmp, target, CopyOption.REPLACE_EXISTING, CopyOption.ATOMIC_MOVE);
} catch (JAXBException e) {
e.printStackTrace();
}
}Note the use of the atomic Files.move(...)` command.
One day, when your file-system is full, and you run out of space... you will appreciate that change.
Code Snippets
public void toXml() {
try {
File file = new File("jcrf.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}public void toXml() {
try {
File file = new File("jcrf.xml.tmp");
JAXBContext jaxbContext = JAXBContext.newInstance(Jcrf.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(this, file);
jaxbMarshaller.marshal(this, System.out);
// move tmp file to complete output file.
Path tmp = file.toPath();
Path target = Paths.get("jcrf.xml");
Files.move(tmp, target, CopyOption.REPLACE_EXISTING, CopyOption.ATOMIC_MOVE);
} catch (JAXBException e) {
e.printStackTrace();
}
}Context
StackExchange Code Review Q#86246, answer score: 2
Revisions (0)
No revisions yet.