Saturday, April 26, 2008

The Kite Runner

I used to read books like crazy before. Now, I watch movie the same way. I wish I had a video store where I can keep watching movie all the day. However, only occasionally you get to watch a movie which touches your heart. Today was one such lucky day, I watched THE KITE RUNNER. I forgot when was the last time I saw a such good movie like this.

Monday, April 21, 2008

How to mount windows shared network drive as linux directory

My development environment in office is CentOS and quite often I have to access a windows network share directory. I hate to open nautilus samba file system access every time to copy/paste into those directory. I can't use my bash console to do that. After some googling, I mounted the windows network share folder to my /home/sajid/team_members directory with this command:


mount -t smbfs -o username=sajid,password=sajid //fileserver/team_members /home/sajid/team_members


Here the username/password is my userid password to access the shared network drive, "//fileserver/team_members" is the location of the network directory.

Now that I could mount the network folder to my local drive, I wanted to automate this task every time I started my computer. So, I added this line to my /etc/fstab file.


//fileserver/team_members /home/sajid/team_members smbfs username=sajid,password=sajid 0 0


So from now on, I can use the network drive just as my local filesystem. Now that I have it fixed, I have to be extra careful not to do rm -rf /home/sajid/team_members/.. ;)

Tuesday, April 8, 2008

How to redirect System.out.println in Java

Did you ever get frustrated with a codebase which has overuse of System.out.println??
May be it is flooding your console or even worse you need to capture the outputs to analyze them....Ever wondered how you can capture your System.out.println() 's of your tomcat application?? Well, you can always use IO Redirect in unix to send the output to a file. You can use find replace to change all System.out.println() to some method call which will write the logs to a file. But being the lazy programmer that I am, I always look for a shortcut. And sometimes I even find one :)
I was working with this code and it had important System.out.println everywhere. I wanted to use trail/grep and stuffs like that with the console logs but I couldn't do that on the application console. So this is what I did to redirect all System.out.println to a log file.

public class MyMainClass {
public static void main(String[] args) throws FileNotFoundException {

File file = new File("/home/sajid/sysout.log");
PrintStream printStream = new PrintStream(new FileOutputStream(file));

System.out.println("1");

System.setOut(printStream);


System.out.println("2");

}
}


Did you ever notice that System.out is just another PrintStream and you can replace it with your own? This is why I love java. You can replace many things with your own implementation. Did I tell you how I replaced the URLClassLoader with my JDBCClassLoader to load classes from Database? Lets keep that story for another post.

Monday, April 7, 2008

How to Hotswap classes in the running jvm?

One of the major pain of every server side java developer is that you have to redeploy your application every time you made a small change to the java classes. Now if you are working with a web application which consists 1500 classes, about 150 servlets(basically webservices), imagine how much time tomcat is gonna take to deploy or even worse redeploy that application.(it takes about 6 mins on my p4 pc). This was a small trick I learned from Masum Bhai at Therap.
JVM comes with a debugging api which actually lets you to change the defination of a class at runtime. These are the following steps you have to do.

1> Download hotswap.jar and put it in the "run-classpath" of your ant script.
2> JVM must start with debugging parameter. So add the following parameters at your java start command:
      -Xint -Xdebug -Xrunjdwp:transport=dt_socket,address=${hotswap.port},server=y,suspend=n
For example, if you are using tomcat, you can add this line at the beginning of the catalina.sh

export JAVA_OPTS="-Xint -Xms256m -Xmx256m -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"
alternatively , you can uset the "tomcat-start" ant task given below to start your tomcat. Just make sure you have the tomcat-home ant property defined.
<property name="date-pattern" value="MM/dd/yyyy kk:mm:ss"/>
<property name="hotswap.port" value="8787"/>

<target name="compile" depends="prepare-common"

description="Compiles the application source code">

<echo message="Compiling the application source code...."/>

<!--enable timestamping upto second level (required for hotswapping)-->
<tstamp>

<format property="class.tstamp" pattern="${date-pattern}" />
</tstamp>

<javac

srcdir="${src.dir}"
destdir="${build.classes.dir}"
verbose="false" debug="true"

listfiles="false">
<!-- Use this when you want to see which files are being compiled -->
<classpath refid="run-classpath"/>
</javac>
</target>



<target name="reload" depends="compile">

<taskdef name="hotswap" classname="dak.ant.taskdefs.Hotswap">

<classpath refid="run-classpath"/>
</taskdef>

<hotswap verbose="true" port="${hotswap.port}">

<fileset dir="${build.classes.dir}" includes="**/*.class">
<date datetime="${class.tstamp}" pattern="${date-pattern}" when="after" granularity="0"/>

</fileset>
</hotswap>
</target>

<target name="tomcat-start"
description="Start Tomcat with hotswapping enabled" >


<exec executable="${tomcat.home}/bin/catalina.sh" >
<arg value="start"/>
<env key="JAVA_OPTS"

value="-Xint -Xdebug -Xrunjdwp:transport=dt_socket,address=${hotswap.port},server=y,suspend=n"/>

</exec>
</target>


The rest is simple! When you change anything in a class/group of classes, just use "ant reload" and you will see the hotswap output like this:

ant reload
Buildfile: build.xml

prepare-common:

compile:
[echo] Compiling the application source code....
[javac] Compiling 1 source file to /home/sajid/projects/cmsstandaloneportal/,tmp/cmsstandaloneportal/WEB-INF/classes

reload:
[hotswap] hotswapping 1 files from /home/sajid/projects/cmsstandaloneportal/,tmp/cmsstandaloneportal/WEB-INF/classes
[hotswap] hotswapping com.x.y.z.p.web.struts.QDispatchAction

BUILD SUCCESSFUL
Total time: 10 seconds



10 seconds! Thats all you need!

I have used this trick with Tomcat, JBoss, and standalone java applications and every time it worked like a charm! I can't tell how much deployment time it saved me. So No doubt its my most favorite ant task to date!

Note Of Caution:
Hotswapping doesn't work when you change the structure of a class (add new method/delete method/rename method). It only works when you change the logic inside a method. Thats what we do most of the time anyway, isn't it?

Sunday, April 6, 2008

How to get the calling method information in Java

I was wondering around in a huge code base trying to figure out whats going on.
I wouldn't say it was a bad code base, but it was done by a single geeky programmer who never cared about the readability because I guess he never thought anyone else would ever try to read it. Anyway, I could see all these meaningful log messages coming out from it but I didn't know from where. I think he never heard of log4j or anything like that but luckily he used a class like this:

public class LogHelper{
public static void log(String log){

System.out.println(log);
}
}

and used it like this:
 1 public class X
2 {
3 public void doA()

4 {
5 Logger.log("doing A");
6

7 //..
8 //..
9 Logger.log("done doing A");

10 }
11
12 public void doB()
13 {

14 Logger.log("doing B");
15
16 //..
17 //..

18 Logger.log("done doing B");
19 }
20 }

So he called this static log method from all over the code base to do the logging.
And the log looked like this:

doing A
doing B
done doing B
done doing A

I desperately wanted to know which class/method/line was calling this method like I am used to in log4j.

Then I thought the calling Thread has this information. The question is how can I get it! After playing a bit with stack information, I came up with this:
public static String getCallingMethodInfo() {
StackTraceElement[] stackTrace ;

try{
throw new Exception();
}

catch (Exception e) {
stackTrace = e.getStackTrace();

}

if(stackTrace != null && stackTrace.length >= 2) {

StackTraceElement s = stackTrace[2];
if(s != null) {

return s.getClassName() + ".(" + s.getMethodName() +"):["+ s.getLineNumber() + "] -:";

}
}

return null;
}
So finally the log method looked like this:
public class LogHelper {
public static void log(String log){

String caller = getCallingMethodInfo();
System.out.println(caller + ": " + log);

}
}

So, finally the logs looked like this:

X.(doA):[5]-: doing A
X.(doB):[14]-: doing B
X.(doA):[9]-: done doing A
X.(doB):[18]-: done doing B
In jdk 1.5 you can actually get the stack information like this:
Thread.currentThread().getStackTrace()
but unfortunately I was working with a 1.4 codebase. But Throwing an exception and catching it back did the trick :)

Having said all that, It will be an insane idea to put this code to production. But can be very helpful when you are trying to understand the code.

Thursday, April 3, 2008

Bla bla bla

My brain has got new formula for interpreting human language..what ever goes in my ear, they get compiled into "bla bla bla"--is it me or people around me??!! Its quite refreshing though since most of the time thats the actual meaning. So what did you say your name was? "Bla"??