Monday, November 17, 2008

Which Class Loader Should I use?

Every Java developer knows thing or two about class loaders in the Java. I am sure there are plenty of articles out there to tell you more about "What class loaders are?" and their significance in the Java language. In this article I would like to go over various different ways you can get hands on a class loader, and which method I use and when and why?

There are two elements you need to know before you can load a class or resource, in a Java application
1) Name of the resource.
2) Location of the resource.

Depending upon the application, developer may or may not know above settings at design time of an application. Below we will discuss, which technique to use depending upon the situation

For example purpose let's assume that there is interface "Foo" and it has corresponding implementation class "FooImpl"

If you know the name and location, then it is pretty simple.

Foo foo = new FooImpl();

If you do not know the name, however if you *know* that resource will be reachable from the same class loader as the executing class, then you can code as below

Class fooClazz = this.getClass().getClassLoader().loadClass("FooImpl");
Foo foo = fooClazz.newInstance(); // assuming there is default constructor

or

Class fooClazz = Class.forName("FooImpl");
Foo foo = fooClazz.newInstance();

If you do not know both the name and location of resource, then it becomes little complicated. Usually this occurs when you are using some framework code, and writing some extensions and you do not have control over how your resources are being loaded (for example in application server) then the above techniques work some times, but below should be safer option


Class fooClazz = Thread.currentThread().getContextClassLoader().loadclass("FooImpl");
Foo foo = fooClazz.newInstance();


When the executing thread gets created it will be assigned class loader of the executing class, however user could be set to any other class loader at any point depending upon needs giving the most flexibility.

Sunday, November 2, 2008

Bitten By Grub, and Rescued by Super Grub

We are writing documents in DocBook format for our upcoming open source project and I needed to use Open Office 2.4 to convert some our old MS Word documents into DocBook format. Yes, now you can use Open Office Writer to save your documents in DocBook format. I was using Fedora 8 and it came with 2.3 version and it did not had easy upgrade option for 2.4 and Fedora 9 supported it. I had been putting off the Fedora 9 upgrade for a while, so, I thought this is good time as any other and popped in the Fedora 9 CD and hit upgrade and every thing went just fine.

...until I removed the CD and rebooted the machine. To my horror the the screen stopped with words

GRUB.

and would not progress any further, and my mind started racing and my hands started to tremble (after all I am a newbie at this Fedora stuff). Then I switched to another spare machine and started googling for the solution, and I came across some thread which mentioned use of Super Grub rescue disk to fix the issues with Grub, with no options at hand I was ready to give Super Grub a try.

So, I popped in the CD for Super Grub and booted the machine again. This time it booted to a menu I can't describe, the options can be be chosen by your tolerance for amount of risk you are willing to take. By now I am literally cursing.


Super Grub Disk (WITH HELP) :-)))
Super Grub Disk (NO HELP) :-|
GRUB => MBR & !LINUX! (1) AUTO ;-)))
GRUB => MBR & !LINUX! (>2) MANUAL |8-)
!LINUX! (1) AUTO
!LINUX! (>2) MANUAL
!WIN! :(((
WIN => MBR & !WIN! :(((((((((((((((((
EASY LIVE SWAP


By now couple of my colleagues who were watching me suffer (and laughing) looked at the menu and suggested I take the option with smiley face, feeling lost I hit 1, and followed directions in couple other screens and Super Grub finished it job. I rebooted again.

This time I saw the Fedora 9 booting screens and rest is history. Though I was skeptical about Super Grub based on its UI, it did it's job exactly right. So THANK YOU Super Grub team.

Wednesday, October 29, 2008

Proxy Object and Equals Method

Couple days back I was debugging a XA transaction related bug and I did not see what calls that JBoss TM is making into the underlying XA resource. So, I thought I will slap in a quick Proxy on top of the XAResource interface to log the methods that are being invoked. Then, things lot little more complicated, I started seeing same XAResource behaving as if they are two entirely different resources in a single transaction, which led me to believe the implementation class for XAResouce may be using "equals" method inside it's "isSameRM" call and thus showing erronious behaviour.

To understand why this was happening I started with following code


public interface Foo {
void doSomething();
}

public class FooImpl implements Foo {
public void doSomething() {
System.out.println("doing something");
}
}

public class Main {
public static void main(String[] args) {

final Foo a = new FooImpl();

Foo aProxy = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class }, new InvocationHandler(){

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

try {
return method.invoke(a, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
});
print("a.equals(a) = " + ((a.equals(a))?"same":"not same"));
print("a.equals(aProxy) = " + ((a.equals(aProxy))?"same":"not same"));
print("aProxy.equals(a) = " + ((aProxy.equals(a))?"same":"not same"));
print("aProxy.equals(aProxy) = " + ((aProxy.equals(aProxy))?"same":"not same"));
}

public static void print(String msg){
System.out.println(msg);
}
}


The output was
---------------------------------------------
a.equals(a) = same
a.equals(aProxy) = not same
aProxy.equals(a) = same
aProxy.equals(aProxy) = not same
---------------------------------------------

this confirmed the object identity behaviour, then I added "equals" method to "FooImpl" as below

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof FooImpl))
return false;
FooImpl other = (FooImpl) obj;
// check any non static stuff here..
return true;
}

That did not change any equality check, which I was expecting, then I thought I should intercept the "equals" method on the Proxy and call the "equals" on the non wrapped object to mimic the original behavior, so I added/modified the following code in "Main" class

Foo aProxy = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class }, new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {

if (method.getName().equals("equals") && args.length == 1){
if (Proxy.isProxyClass(args[0].getClass())){
return args[0].equals(a);
} else {
return a.equals(args[0]);
}
}

return method.invoke(a, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
});

---------------------------------------------
a.equals(a) = same
a.equals(aProxy) = not same
aProxy.equals(a) = same
aProxy.equals(aProxy) = same
---------------------------------------------

Still, I did not see all the contracts of the "equals" method matched. Then, finally I changed code in "FooImpl"s equals method to

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;

if(Proxy.isProxyClass(obj.getClass())){
return obj.equals(this);
}

if (!(obj instanceof FooImpl))
return false;
FooImpl other = (FooImpl) obj;
// check any non static stuff here..
return true;
}

---------------------------------------------
a.equals(a) = same
a.equals(aProxy) = same
aProxy.equals(a) = same
aProxy.equals(aProxy) = same
---------------------------------------------

Now, that made them all equal. However, I was not sure of the last code fragment, is this a viable option? When calling code is asking to check the equality, I was delegating back to a unknown proxy class to handle it (this could pose a lot of issues), but at the same time proxy could have intercepted this to begin with (in certain cases) and returned whatever value it can too. Obviously this will not work with any existing code if I were to use this pattern. Is there any other way to solve this issue? Or is this issue at all?

Wednesday, October 8, 2008

Where it all started!

I have been wanting to enter blogosphere for little while now to keep in touch with my friends and colleagues but never took the initiative until now.

It all started when I was watching the 2008 vice-presidential debate on CNN last week, and I heard Alaska Gov. Sarah Palin calling all "Joe Six Packs" and hockey moms in the nation to come together in saying "never again" to those predatory lenders who is responsible for mortgage meltdown.

That got me thinking as to who is this Joe Six Pack? Am I a Joe Six Pack? Then after couple days light came on in my head, Yes of course I am Joey, but actually then I may be a "Java Six Pack" based on my career so far. Then I started listing what makes
my six pack?
  1. Fedora 9
  2. Java
  3. Eclipse
  4. JBoss
  5. My Work
  6. Open source, etc

there I came about name "Java Six Pack". I thought, hey I may not be intelligent about any of these technologies but now and then I do come across some questions, interesting uses and use cases about all the above time to time, that thought inspired me to start this blog!


So, what is your Six Pack? Please share.