61

I am getting very strange "Premature end of file." exception for last few days on one of our servers. The same configuration XML works fine on another server. We are using Tomcat 5.0.28 on both these servers. This code has been working for ages (7+ years), only after recent server crash, we faced this problem on one of the servers. There is no change in XML as well as Java parsing code. :(

The only difference I can see is in Java versions -

Problem Server java version "1.6.0_16" Java(TM) SE Runtime Environment (build 1.6.0_16-b01) Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)

Working Server java version "1.6.0_07" Java(TM) SE Runtime Environment (build 1.6.0_07-b06) Java HotSpot(TM) 64-Bit Server VM (build 10.0-b23, mixed mode)

Here is the Java code that has been working for several years -

private void readSource(final InputSource in ) {
    try {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(in);
        Element elt = doc.getDocumentElement();

        this.readElement( elt );
    } catch ( Exception ex ) {
        ex.printStackTrace();
        throw new ConfigurationException( "Unable to parse configuration information", ex );
    }
}

And here is the exception.

[Fatal Error] :-1:-1: Premature end of file.
org.xml.sax.SAXParseException: Premature end of file.
        at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at com.circus.core.Configuration.readSource(Configuration.java:706)

I have already tried validating XML and found no errors there. Any idea where else can I look for possible problem?

Any pointers would be highly appreciated!

TIA, - Manish

armstrhb
  • 4,054
  • 3
  • 20
  • 28
Manish
  • 1,735
  • 2
  • 17
  • 30
  • 1
    1. How is the `InputSource` built? 2. How big is the `XML`? 3. Does the `XML` come from a local file, from URL, Database, some other streaming source - perhaps the socket gets disconnected, or the `InputStream` gets closed in the middle of parsing? – npe Jun 20 '12 at 07:23
  • Are you sure that when the server crashed it did not add some special characters? You could try to throw in the XML from one of your working servers and see if it works. – npinti Jun 20 '12 at 07:25
  • @npe - (1) The `InputSource` is built with `FileReader` - `this.readSource( new InputSource( fr ) );` (2) XML is 108.1 KB in size. It has been that way for a long time now. (3) XML comes from local file system. I am also suspecting if `InputStream` is getting closed in between. How can I detect that? And again, wondering why it worked before and not now :( @npinti - I have used fresh XML from SVN and also tried same version in XML validator. It *is* valid XML. – Manish Jun 20 '12 at 07:44
  • @Manish: try to set a breakpoint inside the `FileReader#close()` and see if it's somehow called. Or subclass `FileReader` and add some logging - you could for example dump bytes that are `read()` to see if the file is read completely, or it breaks somewhere. – npe Jun 20 '12 at 07:50
  • @Manish: another question: is the `InputSource` reused, or always created from scratch? – npe Jun 20 '12 at 07:54
  • @npe - `InputSource` is always created from scratch. – Manish Jun 20 '12 at 08:04

8 Answers8

75

It is a problem with Java InputStream. When the stream is read once the file offset position counter is moved to the end of file. On the subsequent read by using the same stream you'll get this error. So you have to close and reopen the stream again or call inputStream.reset() to reset the offset counter to its initial position.

jrd1
  • 10,358
  • 4
  • 34
  • 51
dadob051
  • 759
  • 1
  • 5
  • 3
  • This describes my problem. I used the inputStream twice. However, reset() did not work. So, how can I close and reopen the inputstream? – phe Dec 21 '20 at 14:30
30

This is resolved. The problem was elsewhere. Another code in cron job was truncating XML to 0 length file. I have taken care of that.

Manish
  • 1,735
  • 2
  • 17
  • 30
  • 2
    This solved a problem I had after resolving conflicts on an Android branch. If you have a 0 byte xml file, resources will not be bundled successfully. If you run `find . -type f -empty | grep xml` to find the offending file and remove it, this error goes away. – Patrick Beagan Sep 20 '19 at 14:07
23

This exception only happens if you are parsing an empty String/empty byte array.

below is a snippet on how to reproduce it:

String xml = ""; // <-- deliberately an empty string.
ByteArrayInputStream xmlStream = new java.io.ByteArrayInputStream(xml.getBytes());
Unmarshaller u = JAXBContext.newInstance(...)
u.setSchema(...);
u.unmarshal( xmlStream ); // <-- here it will fail
Zo72
  • 14,593
  • 17
  • 71
  • 103
5

Please make sure that you are not consuming your inputstream anywhere before parsing. Sample code is following: the respose below is httpresponse(i.e. response) and main content is contain inside StringEntity (i.e. getEntity())in form of inputStream(i.e. getContent()).

InputStream rescontent = response.getEntity().getContent();
tsResponse=(TsResponse) transformer.convertFromXMLToObject(rescontent );
ishmaelMakitla
  • 3,784
  • 3
  • 26
  • 32
Amit Ty
  • 51
  • 1
  • 2
4

NEW Occurence of this same error on DECEMBER 6 2021!!!

Sample traces:

XmlBeanDefinitionStoreException: Line -1 in XML document from ServletContext resource [<here a reference to spring context .xml file>] is invalid; nested exception is org.xml.sax.SAXParseException; Premature end of file.
Caused by: org.xml.sax.SAXParseException; Premature end of file.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:201)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:175)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:398)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:282)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:204)
at org.apache.xerces.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:576)
at org.apache.xerces.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:679)
at org.apache.xerces.impl.xs.opti.SchemaDOMParser.parse(SchemaDOMParser.java:527)
at org.apache.xerces.impl.xs.traversers.XSDHandler.getSchemaDocument(XSDHandler.java:2148)
at org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:557)

The HINT:

  1. Apache CAMEL team decided to reorganize CAMEL schema files as usually referenced in XML Spring contexts for instance. Instead of just removing (which would have entailed a neat exception, easy to spot) the http://camel.apache.org/schema/spring/camel-spring-2.16.4.xsd usual schema location, they implemented a HTTP 301 redirect response to HTTPS.

  2. The Apache XERCES library does not throw an error in case of HTTP 301, but assumes it has received an empty file!! That entails weird and erroneous exceptions / putting you on the wrong track as these report the failure linked to the top XML file and not the actually offending schema descriptor

  3. the complete revalidation of all schema descriptors and their XSD dependencies at WAR reload/deploy time (from the data/content repo cache) in our app server platform was totally unexpected... and is totally useless! worse: creating a runtime public network dependency for just reloading already validated components and descriptors (at build time)

1+2+3 above, and BANG! major service disruption: the production server was unable to reload any component with a dependency on CAMEL

Fixings:

Two candidates:

a) in xsi:schemaLocation attributes in XML simply add 's' to the http://camel.apache.org/schema/etc becoming https://.... but accept to live with a public network dependency on every component reload

b) replace all http://... shema locations by classpath:. You will have downloaded all XSD and sub-dependent schemas, and deploy them along with the WAR ensuring a visibility to the classloader. E.g. put the files in java/main/resources/somename.xsd and supply classpath:somename.xsd as schema location path

Bernard Hauzeur
  • 2,317
  • 1
  • 18
  • 25
  • Hi @berhauz. I think that I have similar problem and I cannot manage with it. I've ApacheServicemix 7.0.1 and blueprint with defined conduit (CXF). When I try to deploy it to servicemix I'm receiving `Unable to find namespace handler for http://schemas.xmlsoap.org/wsdl/` followed by `org.xml.sax.SAXParseException: Premature end of file`. I've tried your suggestions but it didn't help. – Marcin Wiśniewski Jun 03 '22 at 11:24
3

If input stream is not closed properly then this exception may happen. make sure : If inputstream used is not used "Before" in some way then where you are intended to read. i.e if read 2nd time from same input stream in single operation then 2nd call will get this exception. Also make sure to close input stream in finally block or something like that.

supernova
  • 3,111
  • 4
  • 33
  • 30
2

Are you sure that the XML file is in the correct character encoding? FileReader always uses the platform default encoding, so if the "working" server had a default encoding of (say) ISO-8859-1 and the "problem" server uses UTF-8 you would see this error if the XML contains any non-ASCII characters.

Does it work if you create the InputSource from a FileInputStream instead of a FileReader?

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
1

In our case it was an empty AndroidManifest.xml.

While upgrading Eclispe we ran into the usual trouble, and AndroidManifest.xml must have been checked into SVN by the build script after being clobbered.

Found it by compiling from inside Eclipse, instead of from the command line.

Community
  • 1
  • 1
Danny Schoemann
  • 1,270
  • 26
  • 41