6

.jspf files are "Java server fragments" -- jsp that is intended only for inclusion () in other .jsp files.

Precompiling all .jsp files is very handy because it exposes syntax errors, missing imports, java code errors, etc. at build time rather than run time. We've all struggled with typos in .jsp not showing up until we view a page. I'm putting an automatic task into ant to precompile all my JSP files. (see http://tomcat.apache.org/tomcat-7.0-doc/jasper-howto.html#Web_Application_Compilation).

Tomcat's jsp compiler jasper2 has built in it an assumption that all jsp files have the '.jsp' file extension. This goes against current recommendations to use .jspf file extensions when appropriate.

THE QUESTION: how to code an ant task that will invoke jasper2 (aka jspC) to precompile all .jsp files, including .jspf files?

David
  • 15,894
  • 22
  • 55
  • 66
TSnyder
  • 437
  • 4
  • 6

2 Answers2

1

-- THE ANSWER

(see discussion below for correction to the other answers related to this)

Use ant helper tasks to build a textual list of .jspf files to compile and pass that to the jasper2 task in the jspfiles attribute. As follows:

<target name="precompilejsp">

    <taskdef name="jasper2" classname="org.apache.jasper.JspC"> 
      <classpath refid="compile.classpath"/>
    </taskdef>

<!-- THIS is the guts of the solution -->
    <!-- Jasper2 refuses to precompile .jspf unless we list them specifically. Boo hoo. -->
    <fileset id="jspffiles" dir="${appdir.build}"> 
      <include name="**/*.jspf"/>
      <include name="**/*.jsp"/> 
    </fileset>

<!-- This turns the set into a textual comma-separated list -->
    <pathconvert targetos="unix" pathsep="," property="app.jspflist" refid="jspffiles"/>
    <!-- echo message="Jspf files are: ${app.jspflist}"/ -->

<!-- Do the precompilation by invoking Jasper2 -->
    <jasper2 
             validateXml="false" 
             uriroot="${appdir.build}"
             jspfiles="${app.jspflist}"
             webXmlFragment="${precompile_tmp_dir}/generated_web.xml" 
             outputDir="${precompile_tmp_dir}">
    </jasper2>

    <!-- Now compile those .java sources to generate any error messages. -->
   <mkdir    dir="${precompile_tmp_dir}/WEB-INF/classes"/>
   <javac srcdir="${precompile_tmp_dir}"
          destdir="${precompile_tmp_dir}/WEB-INF/classes"
            debug="${compile.debug}"
      deprecation="${compile.deprecation}"
         optimize="${compile.optimize}"
        includeantruntime="false">
        <classpath refid="compile.classpath"/>
    </javac>

</target> 

--- DISCUSSION

It has been stated in the referenced What is .jspf file extension? How to compile it? (and elsewhere on the web) that .jspf files are not generally to be compiled on their own, and that they are textually included via a <jsp:include> references from other files. That claim and reasoning are wrong. The Tomcat Jasper .jsp compiler does in fact compile .jspf stand-alone during the normal display-time processing of .jsp and related .jspf files. This can be trivially seen by inspecting /usr/share/tomcat/work/Catalina/localhost/org/youdomain/yourpath/includefile_jspf.java. This .java file is generated as stand-alone code for your .jspf file. Bottom line is that <jsp:include> does not work like C's #include(), rather it includes at runtime the output of the jspf file in the output of the including-file, rather than including the source of the jspf file into the source of the .jsp file as C would have.

The claim in that referenced answer that WEB-INF/somejsp.jsp files cannot be viewed by end users is also false. It is common to put ALL .jsp files in WEB-INF and to reference them in Servlet code gateways mapped in web.xml or other servlet request forwarding mechanisms:

  RequestDispatcher dispatcher = servctxThis.getRequestDispatcher( "/WEB-INF/JSP/thewholepage.jsp" );
  dispatcher.forward(request, response);

So, to be specific, .jsp files in /WEB-INF cannot be directly viewed by end users, but they can be forwarded-to by any servlet OR other JSP file, and do often comprise an entire web response -- <HTML> ... </HTML>. (.jspf, on the other hand, often contain a snippet or fragment of HTML response --- <DIV>header-content</DIV>, for example.

Community
  • 1
  • 1
TSnyder
  • 437
  • 4
  • 6
  • 2
    The discussion bit is wrong: the linked article talks about using `<%@include file="" %>`, which, indeed _is_ like a C `#include` statement. `` _does_, as you stated, work differently, so when including files using ``, don’t use the .jspf extension, but do use it for `<%@include file="" %>` and do exclude those files from compilation as they will be compiled together with the including file. – Raphael Schweikert Sep 15 '15 at 12:12
0

Alternative solution is to just register jspf extension in web.xml:

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jspf</url-pattern>
    </jsp-property-group>
</jsp-config>

Then no changes in Ant scripts would be needed.

Vadzim
  • 24,954
  • 11
  • 143
  • 151