Adding an auxiliary enchancer to OpenJPA
Tuesday, December 2nd, 2008A while back I attempted to create a visualization of the relations that OpenJPA creates between the Java classes that it enhances – the intent was to help better understand a particularly intertwined persistent object graph and see if I couldn’t figure out why we were getting a few strange problems.
The initial approach I took was a hilarious trip into the land of sed, perl and graphviz. It kinda looked like it worked, but didn’t actually
Time passed……more time passed……I learned more……more time passed…….and then I had the wacky notion of tying directly into the Enhancer that OpenJPA uses to create the persistence enabled classes. I haven’t done the visualization yet, but this is what I learned about actually tying in an AuxiliaryEnhancer.
1. Create the AuxiliaryEnhancer
The following code is the minimal you will need. Enter this and then compile – you will need OpenJPA and serp on your classpath.
package com.ij;
import org.apache.openjpa.enhance.PCEnhancer.AuxiliaryEnhancer;
import serp.bytecode.BCClass;
import serp.bytecode.BCMethod;
import org.apache.openjpa.meta.ClassMetaData;
public class Grapher implements AuxiliaryEnhancer {
public void run(BCClass bc, ClassMetaData meta) {
System.out.println("Running Enhancement");
}
public boolean skipEnhance(BCMethod m) {
System.out.println("skipEnhance?");
return false;
}
}
2. Register the enhancer using jar based services
This is something I was only barely aware off – registering concrete implementations of services through jar file meta-data.
- Create a file in a META-INF/services/ directory called org.apache.openjpa.enhance.PCEnhancer$AuxiliaryEnhancer
- Note the dollar sign! That one caught me out for a while: I couldn’t decide whether the dot notation or the dollar notation should be used to reference the nested class.
- This file should simply contain the fully qualified name of the Enhancer you wrote: com.ij.Grapher
- Jar this directory and the class file up and you should end up with a jar listing like this
ivan-jensens-computer:jar ivanjensen$ jar tvf ../grapher.jar 0 Tue Dec 02 21:56:42 PST 2008 META-INF/ 60 Tue Dec 02 21:56:42 PST 2008 META-INF/MANIFEST.MF 0 Tue Dec 02 21:54:28 PST 2008 META-INF/services/ 16 Tue Dec 02 21:30:44 PST 2008 META-INF/services/org.apache.renamed.openjpa.enhance.PCEnhancer$AuxiliaryEnhancer 0 Tue Dec 02 21:55:16 PST 2008 com/ 0 Tue Dec 02 21:55:38 PST 2008 com/ij/ 771 Tue Dec 02 21:55:38 PST 2008 com/ij/Grapher.class 465 Tue Dec 02 21:54:46 PST 2008 com/ij/Grapher.java
3. Add the new jar file to the enhancer classpath
I did this by adding my jar file to the classpath element of my ant script – pretty simple.
4. Re-enhance your classes
Re-enhance your classes and you will see the System.out.println statements all over your console.
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] Running Enhancement
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] skipEnhance?
[openjpac] skipEnhance?
One thing I noticed about this: I had to delete my persistent classes and re-enhance, only then would the ‘run’ method be called. The skipMethod is called whether I delete the classes or not. I don’t know what that means yet, but I’m sure I am about to find out.
Notes:
I was actually using a patched version of OpenJpa 1.0.1 (for various, non-amusing, reasons), but the patches shouldn’t affect this tutorial.