Friday, October 21, 2011

Java Reflection: Invoke Constructor Issue

Let's imagine we have the next classes:

package test.clazz;

public class First {
 private FirstArg arg;

 public FirstArg getArg() {
  return arg;
 }

 public First (FirstArg arg) {
  this.arg = arg;
  System.out.println("First() - constructor");
 }
}

public class FirstArg {
 public FirstArg() {
  System.out.println("FirstArg.FirstArg()");
 }
}

public class SecondArg  extends FirstArg{
 public SecondArg() {
  System.out.println("SecondArg.SecondArg()");
 }
}
And we can easily instantiate First class with FirstArg or SecondArg:
First f1Old = new First(new FirstArg());
First f2Old = new First(new SecondArg());
System.out.println(f1Old.getArg().getClass());
System.out.println(f2Old.getArg().getClass());
We'll get the next output:
FirstArg.FirstArg()
First() - constructor
FirstArg.FirstArg()
SecondArg.SecondArg()
First() - constructor
class test.clazz.FirstArg
class test.clazz.SecondArg

Now, we have to instantiate First class with FirstArg or SecondArg, but via Java reflection:

public final class ConstructionUtil {
 public static Object instantiateClassOld(String className, Object iView) {
  try {
   Class iViewClass = iView.getClass();
   Class clazz = Class.forName(className);

   Constructor ctor = clazz.getDeclaredConstructor(iViewClass);
   ctor.setAccessible(true);
   return ctor.newInstance(iView);
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
} 
Check reflection based class instantiation:
Object cls = instantiateClassOld("test.clazz.First", new FirstArg());
First f1 = (First) cls;
Object cls2 = instantiateClassOld("test.clazz.First", new SecondArg());
First f2 = (First) cls2;
System.out.println(f1.getArg().getClass());
System.out.println(f2.getArg().getClass());
And we'll get Exception:
FirstArg.FirstArg()
First() - constructor
FirstArg.FirstArg()
SecondArg.SecondArg()
java.lang.NoSuchMethodException: test.clazz.First.(test.clazz.SecondArg)
 at java.lang.Class.getConstructor0(Unknown Source)
 at java.lang.Class.getDeclaredConstructor(Unknown Source)
 at test.ConstructionUtil.instantiateClassOld(ConstructionUtil.java:63)
 at test.ConstructionUtil.main(ConstructionUtil.java:22)
Reflection mechanism can't find First(SecondArg arg) constructor.
We have to patch instantiateClassOld method like this:

public final class ConstructionUtil {
 public static Object instantiateClassNew(String className, Object iView) {
  try {
   Class iViewClass = iView.getClass();
   Class clazz = Class.forName(className);
   try {
    Constructor ctor = clazz.getDeclaredConstructor(iViewClass);
    ctor.setAccessible(true);
    return ctor.newInstance(iView);

   } catch (NoSuchMethodException e) {
    Constructor[] constructors = clazz.getDeclaredConstructors();
    for (Constructor c : constructors) {
     if (c.getParameterTypes().length > 1)
      continue;
     Class type = c.getParameterTypes()[0];
     if (type.isAssignableFrom(iView.getClass())) {
      return c.newInstance(type.cast(iView));
     }

    }
   }
   return null;

  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
} 
And run it again:
Object cls = instantiateClassNew("test.clazz.First",new FirstArg());
First f1 = (First) cls;
Object cls2 = instantiateClassNew("test.clazz.First",new SecondArg());
First f2 = (First) cls2;
System.out.println(f1.getArg().getClass());
System.out.println(f2.getArg().getClass());
Output:
FirstArg.FirstArg()
First() - constructor
FirstArg.FirstArg()
SecondArg.SecondArg()
First() - constructor
class test.clazz.FirstArg
class test.clazz.SecondArg
We should be careful when invoke methods via reflection with polymorphic arguments.

Monday, October 10, 2011

Overview: Optimistic vs. Pessimistic Locking

Data Concurrency is a real problem in multi-user environment. How can we manage the data consistence when several users try to modify the same record(s) at the same time?
This is a very interesting subject. Mostly, it's compromise. We can't easily pick one approach and forget about another.
This subject was quite nice discussed in Martin's Fowler book: "Patterns of Enterprise Application Architecture"
And, you can find here the short Martin's overview: Pessimistic Offline Lock and Optimistic Offline Lock.

JBoss community documentation has nice quotes about the subject:
The disadvantage of pessimistic locking is that a resource is locked from the time it is first accessed in a transaction until the transaction is finished, making it inaccessible to other transactions during that time. If most transactions simply look at the resource and never change it, an exclusive lock may be overkill as it may cause lock contention, and optimistic locking may be a better approach. With pessimistic locking, locks are applied in a fail-safe way. In the banking application example, an account is locked as soon as it is accessed in a transaction. Attempts to use the account in other transactions while it is locked will either result in the other process being delayed until the account lock is released, or that the process transaction will be rolled back. The lock exists until the transaction has either been committed or rolled back.
With optimistic locking, a resource is not actually locked when it is first is accessed by a transaction. Instead, the state of the resource at the time when it would have been locked with the pessimistic locking approach is saved. Other transactions are able to concurrently access to the resource and the possibility of conflicting changes is possible. At commit time, when the resource is about to be updated in persistent storage, the state of the resource is read from storage again and compared to the state that was saved when the resource was first accessed in the transaction. If the two states differ, a conflicting update was made, and the transaction will be rolled back.
The most popular example of optimistic locking is SVN commit operation.