ALBERLAU blog

Blog about my personal experience in software development.

Tuesday, March 10, 2009

 

Workaround for SpringFramework NullValueInNestedPath

I faced springframework famous NullValueInNestedPath problem. I found one out of the box solution to workaround this problem. The solution is to create decorator who wraps list and creates null objects lazily jus for display. There is LegacyTransaction object who owns one payer or one payee or both of class Participant. In most cases there is null payer or payee. Of course we can create somewhere those objects. But in case of hibernate they will be persisted. Create fake objects, just to display correct data is not right solution. Example usage is as follows.





List<LegacyTransaction> tr = bnkPmtFacade.loadLegacyTransactions(tf, user, br);
List trDeco=ListDecorator.getInstance(new NullSafeParticipantDecorator(), tr);
mm.addAttribute(BnkPmtSessionKeys.transactions, trDeco);






Actual decorator to create fake objects NullSafeParticipantDecorator.
Source is below :




import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;






public class NullSafeParticipantDecorator implements IListItemDecorator,Serializable{

@Override
public Object decorate(final Object o) {
return Enhancer.create(o.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method mth, Object[] args, MethodProxy mpx) throws Throwable {
Object res = mth.invoke(o, args);
String mname = mth.getName();
if (!mname.equals("getPayer") && !mname.equals("getPayee")) {
return res;
}
LegacyTransaction lt=(LegacyTransaction)o;
if(mname.equals("getPayer")) {
if(lt.getPayer()!=null) {
return lt.getPayer();
} else {
return new Participant();
}
}
if(mname.equals("getPayee")) {
if(lt.getPayee()!=null) {
return lt.getPayee();
} else {
return new Participant();
}
}
throw new RuntimeException("Should never get this!");
}
});
}
}




Below is classes that makes easer to create such kind of decorators
ListDecorator source:



import java.lang.reflect.Proxy;
import java.util.List;

public class ListDecorator {
public static List getInstance(IListItemDecorator deco,List list) {
return (List)Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new ListProxy(list,deco));
}
}




IListItemDecorator source:



public interface IListItemDecorator {
Object decorate(Object o);
}




ListProxy source:



import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Iterator;
import java.util.List;

public class ListProxy implements InvocationHandler {

private IListItemDecorator deco;
private List list;

public ListProxy(List list,IListItemDecorator deco) {
this.list=list;
this.deco = deco;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res;
if (method.getName().equals("iterator")) {
res = Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[]{Iterator.class}, new IteratorProxy(list.iterator(), deco));
} else if(method.getName().equals("get")) {
res=deco.decorate(list.get((Integer)args[0]));
} else {
if(list==null) {
res=null;
} else {
res=method.invoke(list, args);
}
}
return res;
}
}




IteratorProxy source:



import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Iterator;

public class IteratorProxy implements InvocationHandler{
private IListItemDecorator deco;
private Iterator iterator;

public IteratorProxy(Iterator iterator, IListItemDecorator deco) {
this.iterator=iterator;
this.deco=deco;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res;
if(method.getName().equals("next")) {
res=deco.decorate(iterator.next());
} else {
res = method.invoke(iterator, args);
}
return res;
}
}



Comments: Post a Comment

Subscribe to Post Comments [Atom]





<< Home

Archives

January 2008   February 2008   March 2009  

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]