Wednesday, October 24, 2012

Another program to find hot threads in Java VM

Many people know the GUI tools, such as jconsole and JTop, and maybe jvisualvm in latest JDK releases, to monitor and analyze JVM performance.

The tools jconsole together with JTop can be used to indentify threads that take most of the CPU usage. However, they work under GUI environment. In case you work in UNIX, without XServer, plus you don't have the JMX agent started, you may not have such luxury. It may be rare, but did happen in my case: HP UX, no XServer, cannot be attached to another XServer due to production firewall, the JMX agent is not started. Anyway, it's very frustrating.

Here's a tool can benefit the above case: http://weblogs.java.net/blog/brucechapman/archive/2008/03/hot_threads.html. It takes a process id as input, and prints top threads that take most of the CPU usage. In HP UX environemnt, I have to include tools.jar in the classpath:

    ${JAVA_HOME}/bin/java -Xbootclasspath/a:${JAVA_HOME}/lib/tools.jar -jar HotThread.jar 

Without tools.jar, it gives error that "java.lang.NoClassDefFoundError: com/sun/tools/attach/VirtualMachine".
Tried this in development environment, but didn't have chance to try it in production, due to lengthy procedures. Sigh...

Thursday, October 11, 2012

CVS check out on UNIX with ssh

This article describes scenario that both your CVS server and client are on unix boxes, and you want to check out/check in using ssh.

By doing this, you can avoid typing password each time. Other than CVS settings, it mainly discusses how to set ssh login from one unix server to anohter. Here are the steps.

1. On your client unix, you first need to have environment variables below set:
    export CVSROOT=:ext:<your_cvs_account>@<cvs_server_name>:<cvs_root_dir>
    export CVS_RSH=ssh
    export CVS_SERVER=/usr/local/bin/cvs (or where your cvs is installed on server side)
You may put them in .profile file under your home.

2. Generate key pair on client unix using dsa
    cd ~/.ssh ssh-keygen –t dsa 
Just hit “Return” key when prompted with “Enter passphrase”. You’ll then find two new files created: id_dsa and id_dsa.pub.
    cat id_dsa.pub
Copy the content (you'll paste it on server side in next step).

3. Copy the public key to cvs server.
Login to cvs server using your account:
    cd .ssh
    vi authorized_keys
Add a new line at the end, and paste the content (copied from previous step). Save and quit.
Note: it may be authorized_keys2 depends on the ssh version.

4. Do a test on client unix.
    ssh <cvs_server>
It should let you in without asking for password.

5. Now you can use cvs as usual.
    cvs co <cvs_path>

Struts 2: Populate data for page even after validation failed

I recently added a validation interceptor in one of our Struts 2 applications, but got some errors when validation failed. It took me some time to figure out the error since all exceptions have been redirected to a global exception page, and no logging was written.

Anyway, the error is:
The requested list key 'sortTypeList' could not be resolved as a collection/array/map/enumeration/iterator type.
After some investigation, I figured out the reason being that there is a piece of code in the action method to prepare this list to be dispalyed on the jsp page as a drop down list:

    sortTypeList=new ArrayList();
    sortTypeList.add(new KeyValueVO("id", getText("label.id")));
    sortTypeList.add(new KeyValueVO("name", getText("label.name")));

When the validation fails, this piece of code won't run, leaving the list not being populated. Where KeyValueVO is a class contains two Strings: key and value.

To avoid this, Struts 2 provided an interface Preparable, which has one method:
    public void prepare();

I made the action implement Preparable interface and moved the above code to inside prepare method. It worked properly.

My action also contains a few other method for different actions, not all of them will need populate this list. I made the method prepare empty, and move the code to new methods named as prepare(). For example, the list is needed in sort(), and search(), but not delete(). I created new methods for them:

    prepareSort() { // will run before sort() ...
    prepareSearch() { // will run before search() ... 
The prepare methods are invoked by the interceptor below:
    <interceptor-ref name="prepare"/>
So, you'll need to make sure it is on the interceptor stack and it appears before interceptor "validation".
    <interceptor-ref name="prepare"/>
    ... 
    <interceptor-ref name="validation"/> 
The preparable interceptor supports a parameter: alwaysInvokePrepare. By default it's true, meaning the prepare methods will run.

There are more details can be found in http://struts.apache.org/2.2.1/docs/prepare-interceptor.html, and this link shows an additional solution: http://struts.apache.org/2.2.1/docs/how-do-we-repopulate-controls-when-validation-fails.html.