如何解锁由JAXB的unmarhsaller锁定的文件

时间:2013-02-08 04:51:04

标签: jaxb

我使用以下代码在Windows 7 x64上使用JAXB w / Java 1.7.0_03解组XML文件:

 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.");
            }
  }

调用此方法的代码随后会删除XML文件。

如果撤消成功,XML文件将正确删除。但是,如果上面的代码抛出和Exception,例如。在SAXException中,XML文件无限期地保持锁定状态,并且调用代码无法使用File.delete()删除它。

在这种情况下,感觉JAXB没有关闭资源/文件。以某种方式做到这一点是我的责任还是这个错误?

审查Unmarshaller的javadoc并没有说明这一点,谷歌搜索这个问题从2008年开始显示这个旧的,未得到答复的question

2 个答案:

答案 0 :(得分:6)

简短回答

您描述的行为听起来像是JAXB参考实现中的错误。您可以使用以下链接打开票证:

解决方法

而不是从File取消编组,您可以从FileInputStream解组并控制它在解组后自己正确关闭。


LONG ANSWER

我无法重现您所看到的问题。我已经包括了我在下面尝试过的内容。我在Mac上使用JDK 1.7.0_07 x64。

配置服务

以下大多数代码都是从您的问题中复制而来的。我添加了删除输入文件的调用,如果文件仍然存在则输出。

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

下面是我正在使用的简单XML架构。

<?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中

以下是XML输入。根据XML架构,bar元素无效。在Schema上设置Unmarshaller时,此文档将足以导致在执行解组操作时抛出Exception

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <bar>INVALID</bar>
</config>

<强>配置

package forum14765898;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Config {

    public int bar;

}

<强>输出

以下是运行演示代码的输出。它显示了验证异常,在最后一行我们看到XML文件已成功删除,因为它已不存在。

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

答案 1 :(得分:0)

    public CashCountCompleted CashDeposit(String path) throws Exception {
      // TODO Auto-generated method stub
      CashCountCompleted cashCountCompleted = null;
      File file = null;
      FileInputStream inputStram = null;
      try {
            file = new File(path);
      inputStram = new FileInputStream(file);
      JAXBContext jaxbContext = JAXBContext.newInstance(CashCountCompleted.class);
      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
      cashCountCompleted = (CashCountCompleted) jaxbUnmarshaller.unmarshal(inputStram);         
      }catch (JAXBException e) {
          //throw new...        
      } catch (FileNotFoundException e) {
           //throw new...
      }finally{         
            try{
                if(inputStram !=null){
                    inputStram.close();
                }
            }catch(Exception exception){
               //throw new...
            }                 
      }
      return cashCountCompleted;    
}