Instrumentation must die

114 views
Skip to first unread message

Chris Cleveland

unread,
May 18, 2012, 4:26:06 PM5/18/12
to activejd...@googlegroups.com
Instrumentation is really a problem in some circumstances. In our case, we want to compile code in our app on the fly, so it's a no-go. It also adds junk to the Maven POM and just feels flaky. Comments on the Instrumentation wiki page indicate others feel the same way.

How about another approach? Instead of:

Person.where("name=value");

do this:

Person.db().where("name=value");

In the Person class, add one line of code:

public static Person db() { return (new Person()).init(); }

All of the query methods on Person would no longer be static, and they would inherit from the Model class. init() would do any necessary initialization.

I know, I know, this syntax isn't as pretty, but it solves a huge, ugly problem.





ipolevoy

unread,
May 18, 2012, 5:11:30 PM5/18/12
to activejd...@googlegroups.com
Ha, good luck, entire framework revolves around this API:
Person.where("name=value");
making changes you suggest... would probably require writing a new framework.

A better solution would be to use to perform instrumentation in memory. It is possible to create an interceptor agent that will be intercepting class loading, and if a class is a model, it would instrument it at run time. However, this would require to run a program with a special command:
java -javaagent:activejdbc-instrumentation.jar com.yourpackage.YourProgram

This means, you would have to add this parameter to JUnit tests inside your IDE, and also you would have to install instrumentation package a container where you run the app. This of course is a one time deal. 
Instrumentation solves one problem: getting a name of a class from static method. If you have better solution, I'd love to hear that

thanks
igor

Chris Cleveland

unread,
May 18, 2012, 5:32:35 PM5/18/12
to activejd...@googlegroups.com
How would the "instrumentation in memory" work in an IDE? If it only happens at runtime, then an IDE like Eclipse would show a compile error on "Person.where()" because the where() method would not yet have been added to the bytecode.

Chris Cleveland

unread,
May 18, 2012, 5:42:35 PM5/18/12
to activejd...@googlegroups.com
Never mind, my bad. When you extend a class, you also inherit static methods.

Igor Polevoy

unread,
May 18, 2012, 5:54:04 PM5/18/12
to activejd...@googlegroups.com, Chris Cleveland
sorry, this is not accurate, static methods are not inherited, not in
java at least.

See here:
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
Excerpt:
"You can write a new static method in the subclass that has the same
signature as the one in the superclass, thus hiding it."


.. so instrumentation fakes static method inheritance by physically
moving static methods from Model to a subclass, all for a purpose of
beautiful APIs.

thanks
igor

Chris Cleveland

unread,
May 18, 2012, 6:31:33 PM5/18/12
to Igor Polevoy, activejd...@googlegroups.com
What about something like this:

class Person extends Model {
static { Model.init(Person.class); }
}

init() does on-the-fly instrumentation on the Person class. This might help:

http://docs.oracle.com/javase/6/docs/technotes/guides/instrumentation/changes6.html

ipolevoy

unread,
May 18, 2012, 7:53:49 PM5/18/12
to activejd...@googlegroups.com, Igor Polevoy
Ohm this is a good find, worth exploring, however, I would be against having to add this line of code.
Even if instrumentation at runtime is possible, I'm not sure how to trigger it.
for example consider:

Person.where()

If class Person has not been instrumented, how to trigger its instrumentation before this method is called??

thanks
igor

Chris Cleveland

unread,
May 18, 2012, 9:40:00 PM5/18/12
to activejd...@googlegroups.com
The instrumentation would get triggered when the class is loaded. The line of code gets executed at class-load time, before any where() method is called.

ipolevoy

unread,
May 18, 2012, 10:34:26 PM5/18/12
to activejd...@googlegroups.com
having this line of code inside each model is not an option. First, introducing it will break thousands of projects, second it is simply ugly.

Chris Cleveland

unread,
May 21, 2012, 1:04:59 PM5/21/12
to activejd...@googlegroups.com
Indeed, ugly it is.

What about a custom classloader? The trick would be to make sure that the custom classloader was the one to load all Model classes. You can replace the classloader for the current thread, but Model classes may not all get loaded by the same thread. I googled around and looked for a way to replace the system classloader, but did not find it. I'm pretty sure it can be done, though.

Igor Polevoy

unread,
May 21, 2012, 2:12:25 PM5/21/12
to activejd...@googlegroups.com, Chris Cleveland
this was a path I pursued in 2009, when I did instrumentation in
memory. The problem was that it worked ... in most cases.
Unfortunately in some wierd cases, a container (Glassfish at the time)
was loading some classes before loading the web app, basically
preventing from instrumenting an already loaded class. I banged my head
against monitor for two months, then switched to static
instrumentation, and got 100% reliability.
Frankly, I do not view instrumentation as evel, to me it is more a
minor annpyance. I configured my IDE to automaticaly run
instrumentation with Ant before each test, which happens near instant.
Think of any other technology that requires a post-compile step , such
as AspecJ. While I'd like to make it possible to haev instrumentation
in memory, nit sure that the gigangic effort it requires is worth it.
Others stumble on it in teh beginning, but quickly get used to it, the
payoff is good quality consice APIs

Besides, if you practice real TDD, you will not have to recompile your
models on the fly. I would be interested to learn how you use
ActiveJDBC, maybe there are better ways there,\


thanks
Igor
Reply all
Reply to author
Forward
0 new messages