Re: WebObjects classloader fun.
Re: WebObjects classloader fun.
- Subject: Re: WebObjects classloader fun.
- From: Chuck Hill <email@hidden>
- Date: Tue, 3 Apr 2007 09:07:26 -0700
Someone has been having fun!
On Apr 3, 2007, at 2:06 AM, Q wrote:
Oh it gets even more fun.
I thought I would post this just for giggles for anyone interested.
I don't blog, so this will do.
In order to add true groovy "scripting" support (and maybe even BSF
if I can work out how that might work) with rapid turnaround ala
WebScript to my WOGroovy framework I needed to work out how
WebObjects does it's class loading. In hindsight I probably didn't
really need to do this, because the hot class loading in eclipse is
acceptable to some degree, but I wanted to see how it might work
anyway. And to be honest, hot loading is not the best with classes
as dynamic as groovy.
I started by writing a simple class loader wrapper so I could see
what's going on. This allowed me to discover that
com.webobjects.foundation._NSUtilities does some very funky stuff
with partial class name resolution and class caching.
Very, profoundly funky stuff.
(Which prompted my original email asking for help understand what
was going on)
Ok, so I asked my friend "Jad" if he knew anything about
_NSUtilites that might be useful and with what he told me I got my
new best friend GluonJ to watch some function calls that
_NSUtilities makes so I could tell what was actually happening when
my application failed to load my script code.
So with this information, and some magic fairy dust lifted directly
from the now defunct ERXCompilerProxy, I think I have worked out
what I needed to do to make it work, unfortunately it means I
needed to alter some functionality of _NSUtilities and change how
it deals with caching of ClassNotFound exceptions.
Long story short, I now have it working (I think) so that you can
do proper rapid turnaround with groovy code.
Here's the catch. To do rapid turnaround you need to use Java 1.5
with a GluonJ based javaagent (included). It may be possible to get
around this requirement by writing a custom bootstrap loader that
adds the GroovyClassLoader before any of the WebObjects classes are
resolved and somehow force the webobjects classes to be loaded
higher up the loader chain rather than by the system class loader,
but I decided it was easier to write the 3 lines of AOP code and be
done with it.
(the updated code has been checked into subversion http://
code.google.com/p/wogroovy/source , if you want to check it out
this is the only way for now)
If you have been meaning to have a look at AspectJ, JBoss AOP or
similar AOP package for Java, do yourself a favour and look at
GluonJ first, you need to use java 1.5, but it only needs a single
page of documentation. :)
Thanks for that. I have been meaning to look at GulonJ for a while
now. It just got moved higher on the list.
Now that I have got that off my chest I should probably do
something useful and get back to work ;)
:-)
Chuck
On 30/03/2007, at 2:44 PM, Mike Schrag wrote:
Does anyone know much about how webobjects uses the classloader
and how the _NSUtilities class cache is initialized and used?
[snip] it appears that _NSUtilities has a static initialiser that
pulls in and caches classes rather than asking the current thread
context classloader for them when needed [snip]
You are correct ... Frameworks (and your app) are loaded by
NSBundle, which traverses all of the classpath and loads the
reachable classes into the NSUtilities cache (so you can do things
like looking up a component by name -- _NSUtilities.classWithName
(..)). You can also override these class names by calling
_NSUtilities.setClassForName. If the name was not in the cache,
it will Class.forName it and then put the result into the cache.
This behavior makes packageless WOComponent name lookups (for
instance) very fast in exchange for some kind of weird behavior
(like cross-your-fingers-if-you-have-two-classes-with-the-same-name).
Unfortunately, I don't know of any way to REMOVE an entry from the
cache. You can't setClassForName(null, "ClassName") because that
tries to put a null key into the cache. If you specifically know
the class name, you can replace it yourself -- ERXPatcher is
generally just calling setClassForName with classes it replaces.
ms
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40gmail.com
This email sent to email@hidden
--
Seeya...Q
Quinton Dolan - email@hidden
Gold Coast, QLD, Australia
Ph: +61 419 729 806
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40global-village.net
This email sent to email@hidden
--
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve specific
problems.
http://www.global-village.net/products/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden