Sunday, August 19, 2007

Debugging a JSP compilation problem on Tomcat 6

I was doing some experimentation with Maven and Tomcat 6 when I hit this error.
SEVERE: Servlet.service() for servlet jsp threw exception
org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 8 in the generated java file
Only a type can be imported. net.project_00.interview.java.mock.web.SomeThingStupid resolves to a package

An error occurred at line: 17 in the jsp file: /interview-java-mock-web/index2.jsp
SomeThingStupid cannot be resolved
14:
15: <%=new Date()%>
16: <%=new GregorianCalendar()%>
17: <%=SomeThingStupid.getString() %>
18: </body>
19: </html>

Stacktrace:
at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)
........... (rest of stacktrace)

Steps taken to debug the problem

Now, it appears to me that the error message is telling me that net.project_00.interview.java.mock.web.SomeThingStupid is not a type, but a package. I'm very sure that this is not the case after checking my code and package. Eclipse also does not give me this error when I do the import of SomeThingStupid . Conversely, when I import a package like java.util, Eclipse does give me the error.

Then I went to check that my WEB-INF\classes folder in my web-app's folder in Tomcat contained the class in the correct package. It did.

Not sure what's going on, I went to look for the generated Java class for the problematic JSP in $CATALINA_HOME\work\Catalina\localhost. I looked inside the code, nothing fishy there.

So I googled the error message, hoping to find some indication of what went wrong. Nothing useful turned up, all of them talked about importing of a package instead of a type or the exclusion of a required JAR file. Until I hit this Chinese website.

It mentions something about the Context path and docBase not being set correctly. Suspecting that my directory structure is wrong, I took the JSP page in question and copied it to the corresponding page in a web-app I know was working properly. I also copied the entire directory structure corresponding to the fully-qualified name of the class SomeThingStupid to WEB-INF\classes folder of the working web-app. And the result of the test was that it worked.

Then I checked the directory structure of the 2 web-apps and confirmed that the problematic web-app 's directory structure was wrong.

The structure of the working web-app was: $CATALINA_HOME\webapps\examples

The structure of the wrong web-app was: $CATALINA_HOME\webapps\interview-java-mock-web\interview-java-mock-web

The problem was that it was nested under an additional folder called "interview-java-mock-web" instead of being directly under the folder "webapps".

Reason for the difference in directory structure

I had used Maven2 to build the web-app, and part of Maven's advantage is that it makes the management of build life-cycle simple. However, there is a slight problem in executing "mvn clean". As stated in the "Getting Started" guide, this will remove the target directory with all the build data before starting so that it is fresh. Unfortunately, if your target directory is the $CATALINA_HOME\webapps folder, as indicated in the POM file, you will delete the entire webapps folder. This is not what I want. I want to delete only the files pertaining to the project in question and not the entire "webapps" folder, which contains other projects.

Hence my approach is to change the target directory in the POM file to $CATALINA_HOME\webapps\${artifactId}

Setting the Context element


So to resolve the original problem of the compiler not being able to find the class SomeThingStupid, the Context element has to be set in Tomcat. Taking a look at the docs, I created the file $CATALINA_HOME\conf\Catalina\localhost\interview-java-mock-web.xml

The file contains the following line:

<Context path="" docBase="/interview-java-mock-web"> </Context>

Working, but with a warning

Setting the Context element makes my web-app work, it also solves another problem of erroneous servlet mapping. However, there is a warning message when Tomcat starts up. I haven't found time to solve this.
Aug 18, 2007 10:21:06 PM org.apache.catalina.startup.HostConfig deployDescriptor
WARNING: A docBase C:\Program Files\Apache Software Foundation\apache-tomcat-6.0.13\webapps\interview-java-mock-web inside the host appBase has been specified, and will be ignored

No comments:

Post a Comment