[aspectwerkz-user] [patch] DTD error after reload
Mattias Jiderhamn <[email protected]> Tue, 22 Nov 2005 09:41:59 +0100
| Newsgroups | gmane.comp.java.aspectwerkz.user |
|---|---|
| Message-ID | <[email protected]> |
[Nobody answered this in the dev list, so I'll givet it a try on the user list]
I believe I have finally tracked down and fixed a problem with
reading the DTD file after web application reload. Since long we have
experienced now and then that - using online weaving - after the
application has been reloaded a couple of times, the XML parser
claims the DTD is invalid. Here is an example:
com.caucho.xml.XmlParseException:
<http://aspectwerkz.codehaus.org/dtd/aspectwerkz_2_0.dtd:1>http://aspectwerkz.codehaus.org/dtd/aspectwerkz_2_0.dtd:1:
expected '<' at end of file
at com.caucho.xml.XmlParser.error(XmlParser.java:2831)
at com.caucho.xml.XmlParser.parseDoctypeDecl(XmlParser.java:573)
at com.caucho.xml.XmlParser.parseDoctype(XmlParser.java:496)
at com.caucho.xml.XmlParser.parseNode(XmlParser.java:386)
at com.caucho.xml.XmlParser.parseInt(XmlParser.java:240)
at com.caucho.xml.AbstractParser.parse(AbstractParser.java:633)
at org.dom4j.io.SAXReader.read(SAXReader.java:339)
at org.dom4j.io.SAXReader.read(SAXReader.java:261)
at
org.codehaus.aspectwerkz.definition.XmlParser.createDocument(XmlParser.java:229)
...
For long I believed this was a problem with the XML parser, but I
have today discovered that this may rather be a bug within
AspectWerkz in combination with online weaving and a dynamic class loader.
The DTD is located within the AW jar file by a static member in
org.codehaus.aspectwerkz.definition.XmlParser, namely DTD_STREAM.
This (as the name indicates...) is a stream. I believe the problem
occurs because when the stream has been read once, it cannot be read
again. When the web application is reloaded, the classes need to be
re-weaved by AspectWerkz and AspectWerkz tries to parse aop.xml
again. It then uses the same stream, since the AW jar is in the
bootclasspath rather than the application classpath, and therefore
the DTD cannot be read.
The obvious solution - which seem to work so far - is NOT to store
the stream as a static member. Instead we store the URL and
instantiate a new stream for every use. Below you will find a patch
for this (I could e-mail this as a file).
What do you guys think? Is my analysis correct, or is this in fact an
XML parser issue?
Index: src/main/org/codehaus/aspectwerkz/definition/XmlParser.java
===================================================================
RCS file:
/home/projects/aspectwerkz/scm/aspectwerkz4/src/main/org/codehaus/aspectwerkz/definition/XmlParser.java,v
retrieving revision 1.6
diff -u -r1.6 XmlParser.java
--- src/main/org/codehaus/aspectwerkz/definition/XmlParser.java 15
Dec 2004 23:09:06 -0000 1.6
+++ src/main/org/codehaus/aspectwerkz/definition/XmlParser.java 11
Nov 2005 10:59:24 -0000
@@ -47,7 +47,7 @@
/**
* A handler to the DTD stream so that we are only using one
file descriptor
*/
- private final static InputStream DTD_STREAM =
XmlParser.class.getResourceAsStream("/aspectwerkz2.dtd");
+ private final static URL DTD_URL =
XmlParser.class.getResource("/aspectwerkz2.dtd");
/**
* The timestamp, holding the last time that the definition was parsed.
@@ -267,13 +267,15 @@
EntityResolver resolver = new EntityResolver() {
public InputSource resolveEntity(String publicId,
String systemId) {
if (publicId.equals(DTD_PUBLIC_ID) ||
publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
- InputStream in = DTD_STREAM;
- if (in == null) {
- System.err.println("AspectWerkz - WARN -
could not open DTD");
- return new InputSource();
- } else {
- return new InputSource(in);
+ try {
+ InputStream in = DTD_URL.openStream();
+ if (in != null)
+ return new InputSource(in);
}
+ catch(IOException ioex ) {
+ }
+ System.err.println("AspectWerkz - WARN - could
not open DTD");
+ return new InputSource(); // avoid null pointer exception
} else {
System.err.println(
"AspectWerkz - WARN - deprecated DTD "
Mattias Jiderhamn