...begins in wonder

code, poetry, philosophy, folly (Andrew Kuklewicz)

I miss my monkeypatch.

14 Dec 2005

I miss my monkeypatch.

If you have done a decent amount of python code, you've probably run into monkey patching - if you haven't, you're missing out. But in java, where I use an ever increasing number of open source libraries, I missed this lovely feature I was able to use to good effect in Plone. But no more, now there is AspectJ to the rescue.

First off, the problem I had was to extend the code generation capabilities in Axis 1.3 to generate java code from a WSDL (which is better than the other way around). But WSDL2Java extension is limited, and I don't feel like downloading all the Axis source and changing it and recompiling it myself. All I wanted to do was to make the java code that was created include a unique ID to make the objects easier to persist in hibernate (and just to be a show-off, yes I am using Spring too, but not for code generation - it's not good for everything :).

So how to do it? Easy enough, use the cuckoo's egg design pattern to replace Axis's current java class generator with an instance of my own when the constructor is called:

import java.util.Vector;
import org.apache.axis.wsdl.symbolTable.TypeEntry;
import org.apache.axis.wsdl.toJava.Emitter;
import org.apache.axis.wsdl.toJava.JavaBeanWriter;
import org.apache.axis.wsdl.toJava.JavaWriter;
import org.kookster.PersistentJavaBeanWriter;

* Use this to change the behaviour of the WSDL2Java axis code gen
* @author kookster
public aspect ReplaceJavaBeanWriterAspect {

//here's a pointcut to get the public constructor of Axis JavaBeanWriter
public pointcut javaBeanWriterConstructor( Emitter emitter,
                                         TypeEntry type,
                                         Vector elements,
                                         TypeEntry extendType,
                                         Vector attributes,
                                         JavaWriter helper ):
  call( JavaBeanWriter.new( Emitter,TypeEntry,Vector,TypeEntry,Vector,JavaWriter )) &&
  args( emitter,type,elements,extendType,attributes,helper );

//here is the advice which calls the constructor for my object instead
JavaBeanWriter around( Emitter emitter,
                      TypeEntry type,
                      Vector elements,
                      TypeEntry extendType,
                      Vector attributes,
                      JavaWriter helper) :
javaBeanWriterConstructor( emitter,type,elements,extendType,attributes,helper )
  return new PersistentJavaBeanWriter(emitter,type,elements,extendType,attributes,helper);