Validate JSPs at build time

JSPs compile to Java code at run time. This is helpful if we want to test code changes without a build and deploy. However, if errors are introduced, they may not be spotted till it’s too late. A useful compromise is to validate JSPs at build time to verify that they will compile. The validator catches syntax errors before the application deploys and starts. This speeds up our build and test cycle and prevents silly mistakes slipping through to production code.

We can pre-compile JSPs in a Maven build to validate JSPs at build time. Any errors that prevent compilation will halt the build and fail faster.

JSP webapp lifecycle

Here’s a recap of the problem. Regular Java code is written in .java files and then compiled to .class files. On this compilation step, the compiler helps us by checking that the Java code is valid. If the Java code does not compile, the compiler halts and informs us of the error. As a result, it is not possible to deploy invalid Java code to an application server.

JSPs on the other hand are not compiled at build time. Instead, they are simply packaged into a web app (usually a .war file) in plain text. It’s only when the end user requests the page that the application server translates the JSP file to Java code and then compiles it to a .class file. If there is an error in the JSP code causing this translation and compilation to fail, then the user sees an error message. Just to make things worse, the default error page is pretty nasty.

JSP error page

So, it is possible for the developer to introduce an error into a JSP and for no-one to notice until they build it, deploy it and then wait for an end user to access the problem page.

A limited solution

The solution presented here is to shift the JSP compilation step left to build time. This will alert the developer immediately if there’s an error in a JSP. It will also give the team more confidence in automated CI builds – if the application builds then we know there are no JSP syntax errors.

Just to be clear, this solution catches only errors in Java code embedded in JSP scriptlets. It will not catch invalid HTML or JSP tags and it certainly won’t catch plain old logic bugs. Also, I’ll point out that JSPs really shouldn’t contain more than a few lines of trivial Java code, if any. If you find JSPs containing lengthy scriptlet sections, consider moving the Java code out to a Java file where it will be happier. However, this solution is handy for increasing confidence in poorly factored legacy code.

Validate JSPs with jetty-jspc-maven-plugin

The webapp here is a Maven project with the packaging. When we run mvn clean install, Maven compiles all the .java files on the compile phase. It then packages the resulting .class files along with the webapp folder (containing the JSPs) into a war file. We can compile the JSPs on the compile phase too using the jetty-jspc-maven-plugin:

This configuration invokes the jspc goal. It’s bound to the compile phase by default. This means that it’s run immediately after the .java files are compiled.

Note a couple of configuration options here. In both cases this is to override the default plugin behaviour which is to add the compiled JSPs into the webapp. We just want to verify that the JSPs¬†can compile. We’re don’t want to actually package the resulting compiled code into our application.

The result

If all of the JSPs compile, there is no effect on the build at all. The resulting webapp war is identical.

On the other hand, if any JSP fails to compile, the build will fail with an error message like this:

In this case, I’ve just missed a semicolon from the end of a line. The error message is clear and the error is reported when we need it – before the code leaves our machines!

Source code showing how to validate JSPs in this way is in the spanners-mvc project of spanners 3.6, available on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *