I'm unmarshalling an XML file with JAXB w/Java 1.7.0_03 on Windows 7 x64 using the following code:
try (InputStream xsdStream = ConfigurationService.class.getClassLoader().getResourceAsStream(CONFIG_XSD_FILE_NAME)) {
configFile = new File(configFilePath);
if (configFile.exists()) {
context = JAXBContext.newInstance(Config.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
StreamSource xsdStreamSource = new StreamSource(xsdStream);
Schema schema = sf.newSchema(xsdStreamSource);
unMarshaller.setSchema(schema);
Object xmlObject = Config.class.cast(unMarshaller.unmarshal(configFile));
myConfig = (Config) xmlObject;
} else {
log.severe(configFile.getAbsolutePath() + " does not exist, can not parse configuration info from it.");
}
}
Code which calls this method subsequently deletes the XML file.
The XML file will properly delete if unmarhalling is successful. However, if the above code throws and Exception, eg. a SAXException, the XML file remains locked indefinitely and the calling code is not able to delete it with File.delete().
This feels like JAXB is not closing the resource/file in this case. Is it my responsibility to do that somehow or is this a bug?
Reviewing the javadoc for Unmarshaller did not shed any light on this and Googling this issue revealed this old, unanswered question from 2008.
SHORT ANSWER
The behaviour you have described sounds like a bug in the JAXB reference implementation. You can open a ticket using the link below:
Work Around
Instead of unmarshalling from a File
you can unmarshal from a FileInputStream
and control that it is closed correctly yourself after unmarshalling.
LONG ANSWER
I have not been able to reproduce the issue that you are seeing. I have included what I have tried below. I am using JDK 1.7.0_07 x64 for the Mac.
Configuration Service
Most of the code below is copied from your question. I have added the call to delete the input file and then output if the file still exists.
package forum14765898;
import java.io.*;
import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
public class ConfigurationService {
private static final String CONFIG_XSD_FILE_NAME = "forum14765898/schema.xsd";
public static void main(String[] args) throws Exception {
File configFile = null;
String configFilePath = "src/forum14765898/input.xml";
JAXBContext context;
Config myConfig;
try (InputStream xsdStream = ConfigurationService.class.getClassLoader().getResourceAsStream(CONFIG_XSD_FILE_NAME)) {
configFile = new File(configFilePath);
if (configFile.exists()) {
context = JAXBContext.newInstance(Config.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
StreamSource xsdStreamSource = new StreamSource(xsdStream);
Schema schema = sf.newSchema(xsdStreamSource);
unMarshaller.setSchema(schema);
Object xmlObject = Config.class.cast(unMarshaller.unmarshal(configFile));
myConfig = (Config) xmlObject;
} else {
//log.severe(configFile.getAbsolutePath() + " does not exist, can not parse configuration info from it.");
}
} catch(Exception e) {
e.printStackTrace(System.out);
}
configFile.delete();
System.out.println(configFile.exists());
}
}
schema.xsd
Below is the simple XML schema that I am using.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="config">
<complexType>
<sequence>
<element name="bar" type="int"/>
</sequence>
</complexType>
</element>
</schema>
input.xml
Below is the XML input. The bar
element is not valid according to the XML schema. When a Schema
is set on the Unmarshaller
this document will be enough to cause an Exception
to be thrown while performing an unmarshal operation.
<?xml version="1.0" encoding="UTF-8"?>
<config>
<bar>INVALID</bar>
</config>
Config
package forum14765898;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Config {
public int bar;
}
Output
Below is output from running the demo code. It shows both the validation exception and on the last line we see that the XML file was successfully deleted as it no longer exists.
javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; systemId: file:/Users/bdoughan/Scratch/src/forum14765898/input.xml; lineNumber: 3; columnNumber: 23; cvc-datatype-valid.1.2.1: 'INVALID' is not a valid value for 'integer'.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
at forum14765898.ConfigurationService.main(ConfigurationService.java:31)
Caused by: org.xml.sax.SAXParseException; systemId: file:/Users/bdoughan/Scratch/src/forum14765898/input.xml; lineNumber: 3; columnNumber: 23; cvc-datatype-valid.1.2.1: 'INVALID' is not a valid value for 'integer'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:453)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3232)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3147)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3057)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2135)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:854)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:579)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:91)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:143)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1742)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2900)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
... 6 more
false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With