As a Java webdeveloper you are faced with a lot of different aspects of development. One is testing and debugging code, to do this you need an application server like Tomcat. One of the issues I recently encountered was the need to control various Tomcat instances with a single Ant build script. Below are some of the solutions I’ve used to manipulate Tomcat.
Note: some parts of this script rely on the ant-contrib library. Download this library and include it in the tomcat.xml with the following code:
<taskdef resource="net/sf/antcontrib/antcontrib.properties"> <classpath> <pathelement location="./ant-contrib-1.0b3.jar"/> </classpath> </taskdef>
Though starting tomcat may seem easy. You could just use the development IDE (like Netbeans) to start and stop Tomcat, but what this lacks is the ability to control several instances with easy shortcuts. So I defined the following Ant macrodef in a file called tomcat.xml:
<macrodef name="tomcat-start">
<sequential>
<trycatch>
<try>
<if>
<not><http url="http://localhost"/></not>
<then>
<java classname="org.apache.catalina.startup.Bootstrap"
fork="yes"
dir="${tomcat.dir}"
spawn="true"
jvm="${tomcat.java.home}/bin/java">
<jvmarg value="-Dcatalina.home=${tomcat.dir}"/>
<jvmarg value="-Dcatalina.base=${tomcat.dir}"/>
<jvmarg value="-Djava.io.tmpdir=${tomcat.dir}/temp"/>
<jvmarg value="-Djava.endorsed.dirs=${tomcat.dir}/common/endorsed"/>
<jvmarg value="-Xdebug"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"/>
<classpath>
<pathelement location="${tomcat.java.home}/lib/tools.jar"/>
<pathelement location="${tomcat.dir}/bin/bootstrap.jar"/>
</classpath>
<arg line="start" />
</java>
<waitfor maxwait="10" maxwaitunit="second" checkevery="5000">
<http url="http://localhost"/>
</waitfor>
<echo message="Tomcat started"/>
</then>
<else>
<echo message="Tomcat already started..." />
</else>
</if>
</try>
<catch>
<echo message="Unable to start tomcat"/>
</catch>
</trycatch>
</sequential>
</macrodef>
This macro is really easy. First it starts of by checking if tomcat is not already running (well actually it just checks to see if there is something running on port 80). If nothing is running then tomcat is started using the java defined by the ant property tomcat.java.home. This macro also depends on some other properties that are set by a different macro, which will be a bit further on in the post. Tomcat is started by using the Bootloader class provided by the server, to make sure it loads correctly the classpath is set.
The last step in the macro is to wait for tomcat to start, this has to be done since we start tomcat in a seperate java instance (the spawn option).
Off course you also want to be able to stop tomcat to load some new data, or an entire web-app. I use the following macro to stop Tomcat:
<macrodef name="tomcat-stop">
<sequential>
<trycatch>
<try>
<java classname="org.apache.catalina.startup.Bootstrap"
fork="yes"
dir="${tomcat.dir}"
spawn="true"
jvm="${java.home}/bin/java">
<jvmarg value="-Dcatalina.home=${tomcat.dir}"/>
<jvmarg value="-Dcatalina.base=${tomcat.dir}"/>
<jvmarg value="-Djava.io.tmpdir=${tomcat.dir}/temp"/>
<classpath>
<pathelement location="${tomcat.java.home}/lib/tools.jar"/>
<pathelement location="${tomcat.dir}/bin/bootstrap.jar"/>
</classpath>
<arg line="stop" />
</java>
<kill-java name="Bootstrap" />
<echo message="Tomcat stopped" />
</try>
<catch>
<echo message="Unable to stop tomcat forcing shutdown....."/>
<kill-java name="Bootstrap" />
</catch>
</trycatch>
</sequential>
</macrodef>
Just like with the starting of Tomcat I use the provided Bootloader class to instruct tomcat to stop. Again I use the java that is set in tomcat.java.home as well as some other properties loaded by another macro. Since Tomcat sometimes fails to stop gracefully (due to poorly designed webapps) you also have to kill the Java process of Tomcat. This is done with the call to kill-java.
As you saw in the tomcat-stop macro I used a macro called kill-java to make sure that Tomcat is really killed and no longer running in the background. The macro is as follows:
<macrodef name="kill-java"
description="Forcefully stop tomcat....">
<attribute name="name"/>
<sequential>
<!-- Execute the jps and check for any Java process with the provided @{name} attribute -->
<exec executable="${tomcat.java.home}/bin/jps" output="pid.out.file" />
<!-- Load in the name / pid file and strip all information except the PID -->
<loadfile srcfile="pid.out.file" property="pid.out">
<filterchain>
<linecontains>
<contains value="@{name}"/>
</linecontains>
<tokenfilter>
<deletecharacters chars="@{name}"/>
<trim/>
<ignoreblank/>
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadfile>
<echo message="Killing java process with pid ${pid.out}"/>
<!-- Kill the process, warning this only Works on Windows -->
<exec spawn="true" executable="taskkill">
<arg line="/PID ${pid.out}" />
<arg line="/F" />
</exec>
<delete file="pid.out.file" />
</sequential>
</macrodef>
This macro is really simple and relies on the jps application provided by Java. This application returns a list of all running processes with name and process id (PID). All we need to do is get the line containing the process name provided and strip everything except the PID.
Please note: the task killing the proces is designed for Windows, you could change this with kill in Linux.
Though you now have all you need to manipulate tomcat there is one last macro that we are tegenkant upon. That is the initializer of the various Tomcat properties. I use the following macro:
<macrodef name="tomcat-init">
<attribute name="from"/>
<sequential>
<property name="tomcat.dir" value="${tomcat.@{from}.dir}"/>
<property name="tomcat.server" value="${tomcat.@{from}.server}"/>
<property name="tomcat.port" value="${tomcat.@{from}.port}" />
<property name="j2ee.server.type" value="${tomcat.server}" />
<taskdef name="webapp-stop"
classname="org.apache.catalina.ant.StopTask"
classpath="${tomcat.dir}/server/lib/catalina-ant.jar"/>
<taskdef name="webapp-start"
classname="org.apache.catalina.ant.StartTask"
classpath="${tomcat.dir}/server/lib/catalina-ant.jar"/>
</sequential>
</macrodef>
This little macro will initialize tomcat for a specific environment (for exemple DEV). Of course none of this works without the loading of some preset properties in a property file tomcat.properties. Which contains the following data:
tomcat.java.home=C:/jdk1.5.0_22_32b tomcat.DEV.dir=d:/jakarta/tomcat5.0 tomcat.DEV.server=tomcat55-DEV tomcat.DEV.port=8000 tomcat.MAIN.dir=d:/jakarta/tomcat5.0-MAIN tomcat.MAIN.server=tomcat55-MAIN tomcat.MAIN.port=8000
To load the property file just include the following instruction in the build script:
<property file="./tomcat.properties" />
As I recently started a new job I also had to dive into a completely different culture. Programming and code style wise that is. One of the things I came accross was the choice to always use static members. But is this desirable in programming and good conventions.
Personally I think static members should be reserved for helper classes and singleton instances. But why?
One of the main reasons for reserving it for helper classes is simple. A lot of 3rd gen programming languages don’t allow functional programming, hence you need to create a class to support generic functions. In a way you are just trying to store some simple functions in a namespace (C++/.net) or package (Java), but this is not supported. I believe this is fine when all members are static.
A second reason for a static member is to support singleton, or factory model classes. In these situations it is desirable to have one single access point to get an instance of a class. But no other methods should be static.
If you are thinking about making a member static then ask yourself the following question: “Why does this need to be static?”. And the following answers aren’t good once:
So try and be careful when using static members. And as always just keep thinking when programming and designing code.
As I posted before in ‘Mysterious problems with my VPS’, I recently got an increasingly unstable VPS system hosting a lot of my and my customers sites. After a lot of digging I initially presumed that Dovecot (the mail server) was responsible for the issues, as you can read in ‘Dovecot causing memory issues’.
Last week I did a lot of debugging on the Debian server to try and find out what was the issue. And initially it was Dovecots memory usage. After disabling this tool for a couple of days the server was still running fine. However the day after I posted the article on Dovecot the server crashed again. So I had to restart my investigation.
First off I had to had to get a better memory management tool, so I installed Htop on the server (apt-get htop). This shows the current memory usage of each running application. After installing this I enabled all services and applications again and started running stress tests. And though Dovecot was causing some peeks in memory usage it did not keep the high memory usage after the requests where done.
As it turns out for some reason Apache 2.2 was using a lot of memory during peak loads. But even more frustrating it didn’t seem to release any memory any more. Which was causing issues for services that only spawn when they are being accessed like Dovecot and Postfix, which explained why both of these services crashed when the server halted.
After tweaking the maximum amount of servers Apache is allowed to start and the maximum amount of client threads to handle the memory usage dropped dramatically. And I am very happy to report that the server has been running again for more then a week, without any glitches.
Still it doesn’t explain why all of this only happened after updating my server with the latest versions and patches. But I’m glad it’s solved for now.
In my previous post I mentioned that I had and still am having some serious issues with the stability of the VPS I’m running all of my websites on. Though I’m still a long way away from solving the issue, I have figured out that it is very likely caused by an upgrade of Dovecot.
Why I believe that dovecot is slowely over time eating up memory, well after I disabled it the VPS continued running without any issues. I already knew Apache 2, subversion and MySQL weren’t causing it. So I only had postfix and dovecot left to test.
What is truly amazing is that the website for Dovecot indicates it is low in memory consumption, hence it has no settings to limit the amount of memory allocated for Dovecot. So I still need to figure that part out, or alternatively change to a different IMAP server.
I’ve heard a lot of people always say that you can’t crash/hang or break linux easily. Well then I guess I’m one of the lucky bastards that gets it done. Since a few days the VPS system I’m operating keeps hanging itself up.
Now off course it is not the fault of Linux
, but with my very lacking skill. I recently did an apt-get upgrade command on the VPS. To my suprise it started updating with Lenny packages, whilst I could have sworn I have Etch installed. Mystery on its own, but worse yet the server now keeps hanging and breaking.
I figured it was a memory issue at first cause some weird service was installed that was eating it alive. So I de-installed that and it ran fine for a few days. But allas, after 3 days of running the VPS hangs itself up again. When I say hangs-up I mean that I cannot connect using SSH, the mailserver goes down. MySQL and Apache keep running though, as does postfix. So I’m still guessing it is memory, but I have no idea why my configuration is no longer working after running an apt-get upgrade command. Something is really wrong
.