RSS feed
All(28) Eclipse(4) Java(5) JDBC(5) JSP(3) Maven(7) Personal (1) Spring(3) Tomcat(5)
<< Using the Maven SCM Plugin to integrate Maven2 and Subversion | Home | Comparison of 2 Java Excel APIs on Large Workbooks/Worksheets >>

How to handle redeploy of java WARs to tomcat5.5 on Windows and avoid jar file locking

Windows will lock files under Tomcat WEB-INF/lib and prevent redeploys of WARs

At some point recently I began having this problem where windows was locking the jar files in airweb/WEB-INF/lib every time.  Prior I would have 3-4 times while I could redeploy before getting tomcat permgen errors in tomcat before having to stop tomcat manually and delete web application files and restart tomcat and redeploy.

The issue is with windows locking files with tomcat 5.5. The issue was that windows locks files under tomcat and undeploying the war was not succcessful because not all of the jar files in WEB-INF/lib were being deleted while tomcat was running i.e. essentially tomcat 5.5 HotDeploy is not working on windows, so I have to stop tomcat altogether to be able to delete the files. Then restart tomcat and reload the war.

There are several posts about this all over the place. I am using a context.xml with antiJARLocking=true. I am not using antiResourceLocking=true, cause then I cant redeploy jsps on the fly because the jsps are copied into a temp directory under tomcat.

So what I wanted to do was to do the following in a maven script, same would hold if I was just using ant too.

Let say I run the following maven command and what I want to logically happen 

mvn -U clean deploy

        1. Updates from subversion (with mvn-scm-plugin)

2. Manually shuts down the windows service (net stop Tomcat5)

3. Deletes files similar to with ransack

4. unwars the war (instead of remote deploying with maven cargo plugin –saves about 30 seconds)

5.  starts windows service (net start Tomcat5)

6.Checks in code to subversion if a deploy is done (with mvn-scm-plugin)

7.Open a browser with my web application 

Basically this completely removes tomcat hotdeploy and removes the windows file locking issues. If tomcat is not already started script will run to completion but you will see a 2 return code early in the process, however it doesnt halt any subsequent steps.

Essentially I'm running tomcat 5.5 in windows (installed as a service) and I want to start and stop the tomcat5.exe at certain points in my build process. You can do this with the following ant snippets.

I'm using these with the Maven 2 ant run plugin but the same would apply if you were runnning only with ant, windows and tomcat 5.5 as a service.

The key is to use the tomcat exec task with windows cmd.exe and
net start Tomcat5
net stop Tomcat5

Where Tomcat5 is the name of your windows service from the Control Panel - > Administrative Services -> Services -> Properties

These key following assumptions are in play. If this is not the case you may need to modify.

You have tomcat installed at C:/opt/tomcat

You have tomcat installed as a windows service called Tomcat5

You are running the OS Windows XP, if not then change the os in the exec command to match whatever System.getProperty("os.name") returns, otherwise these ant scripts wont fire.

A mvn –U clean deploy took about 1:30 to 1:40 on my machine

A mvn –U clean install took about 1:15

I got the solution idea from these posts

http://mail-archives.apache.org/mod_mbox/tomcat-users/200507.mbox/%3C20050710192642.17A1510FB2B8@asf.osuosl.org%3E

http://ant.apache.org/manual/CoreTasks/exec.html


For example in my web applications pom.xml

            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <id>stop-delete-from-tomcat</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <tasks>
                                <property name="cp"
                                    refid="maven.compile.classpath" />
                                <echo>
                                    Maven Dependency Classpath is ${cp}
                                </echo>

                                <property name="catalina.home"
                                    value="c:/opt/tomcat" />
                               
                                <echo message="Stop Tomcat" />  
                                <exec dir="${basedir}" executable="cmd.exe" os="Windows XP"
                                    output="${catalina.home}/logs/catalina.out" >
                                    <arg line="/c net stop Tomcat5"/>
                                </exec>                                
                                <echo>
                                    Deleting ${artifactId} from tomcat
                                </echo>
                                <echo>
                                    =====================================================
                                </echo>
                                <!-- may or may not be there -->
                                <delete file="${catalina.home}/webapps/${artifactId}.war" />
                                <!-- can only delete if tomcat is stopped -->
                                <delete file="${catalina.home}/conf/Catalina/localhost/${artifactId}.xml" />
                                <delete dir="${catalina.home}/work/Catalina/localhost/${artifactId}" />
                                <delete dir="${catalina.home}/webapps/${artifactId}" />
                               
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>unwar-exploded-start-tomcat</id>
                        <phase>pre-integration-test</phase>
                        <configuration>
                            <tasks>
                                <property name="catalina.home"
                                    value="c:/opt/tomcat" />
                               
                                <unwar src="${basedir}/target/${artifactId}.war" dest="${catalina.home}/webapps/${artifactId}" />
                           
                                <echo message="Start Tomcat" /> 
                                <exec dir="${basedir}" executable="cmd.exe" os="Windows XP"
                                    output="${catalina.home}/logs/catalina.out" >
                                    <arg line="/c net start Tomcat5"/>
                                </exec>
                               
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>open-browser</id>
                        <phase>install</phase>
                        <configuration>
                            <tasks>                           
                                <!-- open browser with homepage -->
                                <property name="browser"
                                    location="C:/Program Files/Internet Explorer/IEXPLORE.EXE" />
                                <property name="url"
                                    value="http://localhost:8080/airweb/login.do" />
                                <exec executable="${browser}"
                                    spawn="true">
                                    <arg value="${url}" />
                                </exec>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
 



Adding a commit comment from eclipse external command to the pom scm checkin/commit

We Determined how to add a checkin comment from eclipse into the maven scm plugins commit step.

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-scm-plugin</artifactId>
                <version>1.0</version>
                <configuration>
                    <connectionType>connection</connectionType>
                    <message>MVN:${scm.message}</message>
                    <includes>
                        src/**,test/**,pom.xml,build.xml
                    </includes>
                </configuration>
                <executions>
                    <!-- svn update -->
                    <execution>
                        <id>update</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>update</goal>
                        </goals>
                    </execution>
                    <!-- svn add -->
                    <!-- svn commit -->
                    <execution>
                        <id>add-checkin</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>add</goal>
                            <goal>checkin</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

And then in the External Command in eclipse for deploying:
Location:
${maven_exec}
Arguments:
-U clean deploy -Dscm.message="${string_prompt:scm.message}"

The last line will give you a prompt or alert box which will set the entered text as a maven property and this will be used the maven scm plugin message and subversion commit comment.


We also tried blocking commits with subversion hooks if they didnt have this MVN comment in them. However this didnt work out very well in practice and we stopped using the subversion hooks to block commits that didnt come from maven. Still since using this we have had much less problems with subversion commited code that wasnt maven deployed. Or maven deployments that werent commited to subversion.

Re: How to handle redeploy of java WARs to tomcat5.5 on Windows and avoid jar file locking

This blog entry is a bit misleading at first. The first three paragraphs sound like you are going to discuss a solution for the problem that web apps sometimes do not undeploy completely because the jar files become locked, requiring the server to be shut down and restarted in order to redeploy.

You then proceed to explain that you use Maven to script the shut down and restart of the server. This does not really solve the problem of the application not undeploying and the need to restart the server.

If you need to test the application against a centralized test server which is shared by other developers and applications you still have the same problem you had before. You cannot redeploy an application without shutting down the server and possibly disrupting other applications. Unfortunately, for me this means I cannot redeploy my applications on the test server as the server admins where I work will not give developers rights to shut down the servers in order to redeploy, and rightfully so.

I do believe that the reason the jars in my applications are locking is something other than Windows though (especially since the test server runs on Unix, though I do use Windows to develop). I know that struts tiles jars were locking because of the use of the DTDs in the tiles definition files. I still have to find out why the jdbc, and poi jars are locking. I have already created a listener to deregister the jdbc drivers for the application when the application stops.

It is too bad there is not a simpler solution which would just remove the classloader when the application is undeployed and free all the files. Jars and resources locking and not allowing undeployment really is a huge headache for something which should be much simpler.


Add a comment Send a TrackBack