Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge jsp pre-compiled web.xml fragment with main web.xml using Ant

We have the usual web.xml for our web application which includes some jsp and jsp tag files. I want to switch to using pre-compiled jsp's. I have the pre-compilation happening in the build ok, and it generates the web.xml fragment and now I want to merge the fragment into the main web.xml.

Is there an include type directive for web.xml that will let me include the fragment.

Ideally I will leave things as is for DEV- as its useful to change jsp's on the fly and see the changes immediately but then for UAT/PROD, the jsp's will be pre-compiled and thus work faster.

like image 336
Chris Kimpton Avatar asked Oct 02 '08 12:10

Chris Kimpton


4 Answers

Doh - there is an option on the jasper2 task to auto-merge the fragment into the main web.xml - addWebXmlMappings

    <jasper2
         validateXml="false"
         uriroot="${web.dir}"
         addWebXmlMappings="true"
         webXmlFragment="${web.dir}/WEB-INF/classes/jasper_generated_web.xml"
         outputDir="${web.dir}/WEB-INF/jsp-src" />

I wonder how good the merge is...

Annoyingly you need to generate the fragment still, even though its not needed after this task.

like image 24
Chris Kimpton Avatar answered Sep 28 '22 16:09

Chris Kimpton


I use the Tomcat jasper ANT tasks in my project, which precompile the JSPs into servlets and add the new servlet mappings to the original web.xml. In the DEV builds, just skip this step and deploy the JSPs without pre-compile and modification of the web.xml.

    <?xml version="1.0"?>
<project name="jspc" basedir="." default="all">
 <import file="${build.appserver.home}/bin/catalina-tasks.xml"/>

 <target name="all" depends="jspc,compile"></target>

 <target name="jspc">
  <jasper
   validateXml="false"
   uriroot="${build.war.dir}"
   webXmlFragment="${build.war.dir}/WEB-INF/generated_web.xml"
   addWebXmlMappings="true"
   outputDir="${build.src.dir}" />
 </target>

 <target name="compile">
  <javac destdir="${build.dir}/classes"
   srcdir="${build.src.dir}"
   optimize="on"
   debug="off"
   failonerror="true"
   source="1.5"
   target="1.5"
   excludes="**/*.smap">
   <classpath>
    <fileset dir="${build.war.dir}/WEB-INF/classes">
     <include name="*.class" />
    </fileset>
    <fileset dir="${build.war.lib.dir}">
     <include name="*.jar" />
    </fileset>
    <fileset dir="${build.appserver.home}/lib">
     <include name="*.jar" />
    </fileset>    
    <fileset dir="${build.appserver.home}/bin">
     <include name="*.jar"/>
    </fileset>
   </classpath>
    <include name="**" />
    <exclude name="tags/**"/>
  </javac>
 </target>

 <target name="clean">
  <delete>
   <fileset dir="${build.src.dir}"/>
   <fileset dir="${build.dir}/classes/org/apache/jsp"/>
  </delete>
 </target>
</project>

If you already have the JSP compilation working and just want to merge the web.xml files, a simple XSLT could be written to add selected elements(such as the servlet mappings) from the newly generated web,xml into your original.

like image 191
Mads Hansen Avatar answered Sep 28 '22 16:09

Mads Hansen


Because the generated fragment is not a valid XML file ( it's a fragment after all ), it is not possible to use XSLT directly. On the other hand you don't have to. Here is a simple trick that will give you exactly what you need.

In your web.xml file insert XML comment <!-- @JSPS_MAP@ --> between <servlet> and <servlet-mapping> elements, e.g.

  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>my.servlets.MyServlet</servlet-class>
  <servlet>

  <!-- @JSPS_MAP@ -->

  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/my-servlet</url-pattern>
  </servlet-mapping>

Then use a token filter to replace @JSPS_MAP@ tag with generated content.

<loadfile
  property="generated.web.xml.fragment"
  srcFile="${generated.fragment.file}"
/>

<copy file="${orig-web-content.dir}/WEB-INF/web.xml"
  toFile="${generated-web-content.dir}/WEB-INF/web.xml"
>
  <filterset>
    <filter token="JSPS_MAP"
      value=" --&gt; ${generated.web.xml.fragment} &lt;!-- "
    />
  </filterset>
</copy>

This approach has an advantage that the original web.xml file is completely valid (a tag is hidden in the comment), but gives you total control of where and when the generated fragment will be inserted.

So for DEV build, just copy ${orig-web-content.dir}/WEB-INF/web.xml to ${generated-web-content.dir}/WEB-INF/web.xml without filtering.

like image 39
Alexander Pogrebnyak Avatar answered Sep 28 '22 15:09

Alexander Pogrebnyak


There is the jasper2 ant task others have noted. I thought I'd mention a couple of other options I've found.

One is cactus' webxmlmerge ant task, which uses org.codehaus.cargo.module.webapp.WebXmlMerger

Another would be to use JAXB to manipulate the web.xml; Sebastien Dionne's dtd-schemas-generator demo does this. Not sure what the license is though.

fwiw having considered these options i think I'm going to use the ant XSLT task.

like image 24
JasonPlutext Avatar answered Sep 28 '22 15:09

JasonPlutext