https://bz.apache.org/bugzilla/show_bug.cgi?id=62603

            Bug ID: 62603
           Summary: Changes in tag files are not reflected in the rendered
                    view or they end up with a
                    java.lang.NoClassDefFoundError
           Product: Tomcat 8
           Version: 8.5.24
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Jasper
          Assignee: dev@tomcat.apache.org
          Reporter: jlla...@gmail.com
  Target Milestone: ----

We have an application that contains jsps and tag files, when we deploy jsp/tag
changes instead of reloading the webapp entirely we change those in the webapps
folder, and let jsp reloading process do the work for us. 

>From time to time, we suffer from two different kind of errors:

1- java.lang.NoClassDefFoundError because the tag file used in a jsp is "not
found", but the jsp and also the tag file are there
(TOMCA_HOME/work/Catalina/localhost/ROOT/org/apache/jsp/...)

2- changes in a tag file are never reflected in the rendered view(jsp)


I've took some time to debug the jsp reloading code, and here are my thoughts

Jsp reloading process at the end is calling JspServlet.periodicEvent method
which triggers the process by calling JspRuntimeContext's checkUnload and
checkCompile methods

JspRuntimeContext's jsps attribute is the one that contains jsps and tag
references that are going to be checked from time to time, depending on
checkInterval and development config values, to see if a JSP page (and its
dependent files) need to be recompiled.

JspRuntimeContext's jsps attribute is backed by a ConcurrentHashMap, so the
insertion order MAY NOT be preserved when we iterate through the list of jsps
and dependant files. Check JspRuntimeContext.checkCompile() method.

The order in which we iterate through the tags and jsps is relevant because
when a change in a tag file is detected the .java and also .class files are
generated and its JspServletWrapper.reload attribute is set to true, afterwards
in the same JspRuntimeContext.checkCompile() loop, when the process detects
that a jsp needs to be recompiled because is "dependant" on this tag file 
TagFileProcessor.loadTagFile method will invoke the
JspServletWrapper.loadTagFile method that belongs to the modified tag, and
because its reload attribute was set to true JSpServletWrapper's tagHandler
attribute will be loaded again. After this process the .java and .class file
that belong to that jsp will be generated 

But what would happen if we :
- detect a change in the jsp first and generate the .java and .class files (jsp
needs to be recompiled because of a change in one dependant tag). 
- receive a request that match that jsp which will set JspServletWrapper.reload
attribute(set to true in the previous step) to false while still "pointing" to
the old tag class
- detect the change in the tag file which will recreate .java and .class files

Then, depending on the order of the incoming request and the jsp detection
process :
- tag changes are not reflected in the rendered view
- or even worse java.lang.NoClassDefFoundError

Sorry for this long description but it's not easy to explain :)

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to