0

My question derives from an upgrade from Tomcat 6.0.18 to 7.0.22, although it seems likely the issue arises in other versions. I suspect it stems from my misunderstanding of Tomcat's core behavior, although after a search of the Tomcat documentation, previous SO questions about Tomcat (too numerous to effectively cite), and a variety of blog posts from various sources (again not on-topic enough to be worth citing), I'm at a loss.

The application I'm working with is a sprawling java app with hundreds of JSP pages. In the past, on Tomcat 6, we've had no trouble compiling them at runtime. They (for the most part) correctly generate *_jsp.java files within Tomcat's work directory, and the compilation to *.class files works as expected. Those that don't are legacy code that is unused in production settings, still in the codebase for reasons not worth specifying here.

When moving to Tomcat 7, specifically 7.0.22, I encountered unexpected behavior. The vast majority of the JSP pages compile (both to .java code and to their affiliated .class files) just fine into the work directory. Some, however, generate 0-byte .java files.

My first take at this problem was: "Something about Tomcat JSP compilation changed between the two versions, other then the JSP specification itself." After poking around in the docs, nothing seemed obvious, so I attempted to pre-compile all the jsps using Ant.

This succeeded insofar as the conversion to .java files was concerned, using an extremely simple ant script:

<project name="myApp" default="all" basedir=".">
    <import file="${tomcat.home}/bin/catalina-tasks.xml"/>
    <target name="jspc">
        <jasper
            validateXml="false"
            uriroot="${webapp.home}"
            webXmlFragment="${webapp.home}/WEB-INF/generated_web.xml"
            outputDir="${webapp.home}/WEB-INF/classes"
            failonerror="false" />
    </target>
    <target name="all" depends="jspc">
    </target>
</project>

*_jsp.java files were correctly generated by jasper, and the 0-byte files that caused trouble when compiled by Tomcat into the work directory were compiling properly with this method. There were a few minor differences when compared with Tomcat 6's work directory *_jsp.java files, but they seem likely related to the JSP spec version upgrade between 6 and 7. Unfortunately, our legacy code makes some of the resulting .java files uncompilable, generally, in both versions. Making them compile from .java to .class (as opposed to .jsp to *_jsp.java to *_jsp.class) would require a deep refactor. Thus, I'm unable to pursue a true JSP pre-compilation strategy. Tomcat appears to handle these files more intelligently then my scripts, which isn't at all surprising.

My question, then, is a bit broader: What might cause tomcat to generate empty *_jsp.java files in its work directory? As a corollary, by what process does Tomcat generate those files in its work directory, and how does that differ from the way I might generate those files with an Ant script? I suspect a deeper understanding of Tomcat's core behavior might yield an obvious solution, an explainable problem, or at least an answer like "This is designed. Please refactor."

skaffman
  • 398,947
  • 96
  • 818
  • 769
Christopher
  • 42,720
  • 11
  • 81
  • 99
  • I don't know for the 0-bytes files, but if the legacy non compiling JSPs aren't used, why don't you just delete them. And if they're used, why don't you fix them? – JB Nizet Jan 11 '12 at 07:16
  • Some of them are unused legacy files that I'm making an effort to remove. Others are older [JSPs that don't follow best practices](http://stackoverflow.com/a/3180202/877115). I'd love to fix the troubled code, as pre-compilation seems like a great idea for performance reasons, but unfortunately a refactor would be a non-starter for my organization. – Christopher Jan 11 '12 at 15:19
  • Do they compile or do they not compile? If they don't compile, they don't need refactoring: they need to be fixed or removed. If they don't compile with pre-compilation, the won't compile in Tomcat either. – JB Nizet Jan 11 '12 at 15:27
  • 1
    They compile when included in other files. The logic gets messy fast (and is unfortunately not up to me), but think of fileA, fileB, and fileC. Neither A nor C compile individually, but when both are included in B with a standard include directive, B compiles just fine. There are maybe a half dozen As and Cs, but there are dozens, if not more than a hundred, Bs, hence the refactoring problem. Tomcat's core internals handle this bizarre situation just fine. As the jasper Ant task doesn't allow exclude elements, I couldn't find a way to script "just compile these JSPs but not these." – Christopher Jan 11 '12 at 16:13
  • It occurs to me that I cannot exclude them from jasper compilation, but I can from javac compilation. I'm going to attempt that with an Ant script, and then programmatically remove the troubled servlets from the generated XML fragment. It's a kludge, and a messy one, but might work. Regardless, I'd love to track down answers to the questions in the bottom paragraph, above. Thus I'm going to leave the question open. – Christopher Jan 11 '12 at 17:36

1 Answers1

0

We had a similar problem and found the cause in our context: we were running a selenium test in our continuous integration environment as soon as tomcat started, so deployment had not completed yet, and that somehow produced the 0 length (empty) *jsp.java and *jsp.class files. The interesting thing is that this happened for all builds, because deployment always took longer (around 1m) than what it took start running the tests.

We fixed it by introducing a delay to allow the internal tomcat deployer to complete its work.