[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