6

次のコードを使用して、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 ファイルは適切に削除されます。ただし、上記のコードが例外をスローした場合、たとえば. SAXException の場合、XML ファイルは無期限にロックされたままになり、呼び出し元のコードは File.delete() でそれを削除できません。

この場合、JAXB がリソース/ファイルを閉じていないように感じます。どういうわけかそれを行うのは私の責任ですか、それともこれはバグですか?

Unmarshallerのjavadocを確認しても、これについて何の光も当てられず、この問題をグーグルで検索すると、2008 年から のこの古い未回答の質問が明らかになりました。

4

2 に答える 2

8

簡潔な答え

あなたが説明した動作は、JAXB リファレンス実装のバグのように聞こえます。以下のリンクを使用してチケットを開くことができます。

回避策

a からアンマーシャリングする代わりに、 a からアンマーシャリングし、アンマーシャリング後に自分で正しく閉じられるように制御Fileできます。FileInputStream


長い答え

表示されている問題を再現できませんでした。私が試したことを以下に含めました。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());

    }

}

スキーマ.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>

入力.xml

以下は XML 入力です。barXML スキーマによると、要素は有効ではありません。このドキュメントにaSchemaが設定されている場合、非整列化操作の実行中に an がスローさ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
于 2013-02-08T11:12:19.400 に答える