Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

WebLogic Server 6.1 SP 3 DocumentBuilder throws IOException: Stream closed

2 views
Skip to first unread message

Jim Doyle

unread,
Oct 17, 2002, 6:21:17 PM10/17/02
to
Hi,

I have a question about XML processing and error handling, and how the
WebLogic container affects things.

Here's what happens to us. We have a servlet parsing XML using DOM.
The servlet has an InputStream with the content. It gets the default
DocumentBuilderFactory
(weblogic.xml.jaxp.RegistryDocumentBuilderFactory) and makes it
validating. It asks for a DocumentBuilder. It gives the builder our
own custom error handler to collect up all the SAX parse errors. It
then tells the builder to parse the input stream. We would expect
that any problems with the content would be reported as an error to
our error handler, so that we can then report the errors to the user
as part of the servlet response.

However, certain malformed XML content causes the WebLogic parser to
issue several error messages to System.out and throw an IOException
with the message "Stream closed". No errors are recorded in our error
handler. This happens on a variety of inputs, which all revolve
around the root element start tag being malformed or entirely missing.
We get this behavior with a totally empty stream, with a stream that
has the <?xml> and <!DOCTYPE> headers but nothing else, with a stream
that has the headers and then a malformed start tag like
"<Submit_Contracts a="1"b="2"/>". I think the programmer would expect
any of these inputs to cause the parser to simply report a fatal error
and stop. Throwing an IOException makes it look like it's an error in
the underlying stream, and clearly it's not. (Most of the test code I
used actually pulled the XML from a ByteArrayInputStream.)

Shouldn't WebLogic's parser handle these inputs differently? Throwing
an IOException can't be correct, can it? Should the application
instead be responsible for checking that the input has a well-formed
start tag? In that case the application is doing the parsing that we
want to rely on the parser to do! Should the application instead
catch IOExceptions from the parser and report them to the user as
input errors? In that case the application can potentially swallow
and ignore harmful system errors.

The messages on System.out are all along the lines of:
"<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Failed to open XML
document. Failed to retrieve PUBLIC id or SYSTEM id from the document.
Decrease the number of char between the beginning of the document and
its root element.>
<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Failed to open XML
document. Failed to retrieve PUBLIC id. Stream closed>
<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Failed to parse given XML
document. Failed to retrieve PUBLIC id. The root element is required
in a well-formed document.>
...
<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Failed to parse given XML
document. Failed to retrieve SYSTEM id. The root element is required
in a well-formed document.>
...
<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Failed to open XML
document. Failed to retrieve root tag. Stream closed>
<Oct 17, 2002 5:38:03 PM EDT> <Error> <XML> <Could not instantiate
factory class specified in the Server console. Invalid parameters: at
least one of publicId,systemId, rootTag must be non-null>
..."

The IOException looks like:
"java.io.IOException: Stream closed
at java.io.BufferedInputStream.ensureOpen(BufferedInputStream.java:118)
at java.io.BufferedInputStream.read(BufferedInputStream.java:268)
at weblogic.apache.xerces.utils.ChunkyByteArray.fill(ChunkyByteArray.java:230)
at weblogic.apache.xerces.utils.ChunkyByteArray.<init>(ChunkyByteArray.java:106)
at weblogic.apache.xerces.readers.DefaultReaderFactory.createReader(DefaultReaderFactory.java:153)
at weblogic.apache.xerces.readers.DefaultEntityHandler.startReadingFromDocument(DefaultEntityHandler.java:499)
at weblogic.apache.xerces.framework.XMLParser.parseSomeSetup(XMLParser.java:318)
at weblogic.apache.xerces.framework.XMLParser.parse(XMLParser.java:974)
at weblogic.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:183)
at weblogic.xml.jaxp.RegistryDocumentBuilder.parse(RegistryDocumentBuilder.java:140)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:86)
at com.isone.sms.participant.contracts.web.WebLogicParserContainerTest.testWebLogicParserTanksOnEmptyStream(WebLogicParserContainerTest.java:448)
at java.lang.reflect.Method.invoke(Native Method)
at junit.framework.TestCase.runTest(TestCase.java:166)
at junit.framework.TestCase.runBare(TestCase.java:140)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:131)
at junit.framework.TestSuite.runTest(TestSuite.java:173)
at junit.framework.TestSuite.run(TestSuite.java:168)
at com.isone.sms.participant.contracts.web.ContractTestServlet.doPost(ContractTestServlet.java:23)
at com.isone.sms.participant.contracts.web.ContractTestServlet.doGet(ContractTestServlet.java:16)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:265)
at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:200)
at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:2546)
at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2260)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:139)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:120)"

Judging from the IOException, it looks as though WebLogic's wrapper
parser, RegistryDocumentBuilder, successfully picked a real parser to
do its work and is passing off the input to be parsed there, even
though the input's already closed. Perhaps the
RegistryDocumentBuilder silently screwed up the stream while trying to
figure out what parser to use, but didn't take that into account
before attempting to pass it off for parsing. Perhaps the error
messages on System.out account for when RegistryDocumentBuilder is
screwing up the stream.
But if RegistryDocumentBuilder discovers that the stream can't be
parsed, why can't it simply report a fatal error and stop before
starting the real parser?

Mainly I wanted to put this experience up here on a newsgroup because
I was so surprised that nobody else had reported similar problems. It
makes me doubt whether our applications are handling the XML parsing
correctly. But I can't see any other way that makes sense. Please
let me know what you think!

Thanks,
Jim

0 new messages