I have encountered with I/O issue in my java program. My program uses java 7 with Tomcat 7 under Linux. Thread 1 creates an object and serialize it to file with JAXB:
public static void export1(JAXBContext context, Object object, Path filePath){
try {
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.marshal(object, filePath.toFile());
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
Then a notification is sent to external entities. Threads that handles incoming requests encounter with:
Caused by: java.nio.file.NoSuchFileException: PATH_TO_FILE
at sun.nio.fs.UnixException.translateToIOException(Unknown Source)
at sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(Unknown Source)
at java.nio.file.Files.newByteChannel(Unknown Source)
at java.nio.file.Files.newByteChannel(Unknown Source)
I have read some posts about I/O concept flush vs sync but I am still confused. Will refactor my code to the next code that uses unbuffered output stream solve my issue?
public static void export2(JAXBContext context, Object object, Path filePath){
try (OutputStream os = Files.newOutputStream(filePath)) {
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.marshal(object, os);
} catch (JAXBException | IOException e) {
throw new RuntimeException(e);
}
}
Or should I use File descriptor directly to synchronize OS buffers with underlying device?
public static void export3(JAXBContext context, Object object, Path filePath) {
try (FileOutputStream fos = new FileOutputStream(filePath.toFile())) {
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.marshal(object, fos);
fos.getFD().sync();
} catch (JAXBException | IOException e) {
throw new RuntimeException(e);
}
}