Knut Wannheden wrote:
Hi - I took the javassist approach now, the code follows.
I get an exception at classFab.addField("_delegate", topClass); in the
createInfrastructure method.
The error is: Unable to process content of element construct/service:
Unable to lookup $PooledProxy_1040a2b0b42_32:
$PooledProxy_1040a2b0b42_32 (DefaultErrorHandler.java:37)
Can you see why?
import java.lang.reflect.Constructor;
import java.util.Iterator;
import java.util.List;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.InterceptorStack;
import org.apache.hivemind.ServiceInterceptorFactory;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.methodmatch.MethodMatcher;
import org.apache.hivemind.service.ClassFab;
import org.apache.hivemind.service.ClassFabUtils;
import org.apache.hivemind.service.ClassFactory;
import org.apache.hivemind.service.MethodContribution;
import org.apache.hivemind.service.MethodIterator;
import org.apache.hivemind.service.MethodSignature;
import org.apache.hivemind.service.impl.ClassFactoryImpl;
/**
* @author David J. M. karlsen
*
*/
abstract public class AbstractInterceptorFactory implements
ServiceInterceptorFactory {
private ClassFactory factory = new ClassFactoryImpl();
/* (non-Javadoc)
* @see
org.apache.hivemind.ServiceInterceptorFactory#createInterceptor(org.apache.hivemind.InterceptorStack,
org.apache.hivemind.internal.Module, java.util.List)
*/
public void createInterceptor(InterceptorStack stack, Module module,
List parameterList) {
Class interceptorClass = constructInterceptorClass(stack,
parameterList);
try {
Object interceptor = instantiateInterceptor(stack,
interceptorClass);
stack.push(interceptor);
}
catch (Exception e){
throw new ApplicationRuntimeException("Problem adding interceptor to
service " + stack.getServiceExtensionPointId(), e);
}
}
private Object instantiateInterceptor(InterceptorStack stack, Class
interceptorClass) throws Exception {
Object stackTop = stack.peek();
Constructor constructor = interceptorClass.getConstructors()[0];
return constructor.newInstance( new Object[] {stackTop} );
}
private Class constructInterceptorClass(InterceptorStack stack, List
parameterList){
Class serviceInterfaceClass = stack.getServiceInterface();
String name =
ClassFabUtils.generateClassName(serviceInterfaceClass.getName());
ClassLoader classloader =
stack.getServiceModule().getClassResolver().getClassLoader();
ClassFab classFab = factory.newClass(name, Object.class,
classloader);
classFab.addInterface(serviceInterfaceClass);
createInfrastructure(stack, classFab);
addServiceMethods(stack, classFab, parameterList);
return classFab.createClass();
}
private void createInfrastructure(InterceptorStack stack, ClassFab
classFab){
Class topClass = ClassFabUtils.getInstanceClass(stack.peek(),
stack.getServiceInterface());
classFab.addField("_delegate", topClass);
classFab.addConstructor( new Class[] { topClass }, null, "{ _delegate
= $1; }" );
}
private void addServiceMethods(InterceptorStack stack, ClassFab
classFab, List parameterList){
MethodMatcher matcher = buildMethodMatcher(parameterList);
MethodIterator mi = new
MethodIterator(stack.getServiceInterface());
while (mi.hasNext()){
MethodSignature sig = (MethodSignature) mi.next();
if ( includeMethod(matcher, sig) ){
addServiceMethodImplementation(classFab, sig);
}
else {
addPassThroughMethodImplementation(classFab,
sig);
}
}
}
private MethodMatcher buildMethodMatcher(List parameters){
MethodMatcher result = new MethodMatcher();
Iterator i = parameters.iterator();
while (i.hasNext()){
MethodContribution mc = (MethodContribution) i.next();
result.put(mc.getMethodPattern(), mc);
}
return result;
}
private boolean includeMethod(MethodMatcher matcher, MethodSignature
sig){
if (matcher == null){
return true;
}
MethodContribution mc = (MethodContribution) matcher.get(sig);
return (mc == null) || mc.getInclude();
}
abstract void addServiceMethodImplementation(ClassFab classFab,
MethodSignature sig);
abstract void addPassThroughMethodImplementation(ClassFab classFab,
MethodSignature sig);
David,
Yes all method calls will go through the interceptor you add. It is
thus up to the interceptor to decide whether it should actually do
something or just pass on to the delegate. For the interceptor to know
what to do the interceptor factory must pass the parameters (in your
case <include> and <exclude>) on (e.g. through the interceptor
constructor).
If you like you can also take a look at HiveMind's logging interceptor
LoggingInterceptorFactory. It uses Javassist to create an interceptor
class and an instance thereof on the fly. The <include> and <exclude>
method matching logic is encapsulated directly by this generated
class. You may of course also prefer the dynamic proxy approach and
code a generic interceptor class yourself. YMMV.
HTH,
--knut
On 5/9/05, David J. M. Karlsen <[EMAIL PROTECTED]> wrote:
Knut Wannheden wrote:
Super! Exactly what I needed! Over to the next problem:
I only want to profile some of the methods called, my config:
In my service-declaration:
<interceptor service-id="ProxyTimingInterceptor">
<include method="*execute*"/>
<exclude method="*"/>
</interceptor>
but still, all methods are going through the interceptor.
Any ideas?
David,
In the interceptor factory implementation you get passed the
InterceptorStack object, which declares a getServiceInterface()
method. You should be able to pass that into the constructor of your
interceptor. The Class returned by getServiceInterface() will be a
synthesized interface if the service in question is a bean service.
I'm writing an interceptor for timing of method-calls (based on jamon).
I want to get the name of the implemented service-interface from the
delegate passed to the constructor. (Following the example at:
http://jakarta.apache.org/hivemind/hivemind-examples/logging.html)
How could I get the name the easiest way possible? Is there a
helper-class somewhere? How am I assured to get the name of the
interface of the service (in all cases, the delegate is another class
depending on service-model, other interceptors and so on). I want to
avoid a lot of introspection and checking on Hivemind specific
service-models etc.).
--
David J. M. Karlsen - +47 90 68 22 43
http://www.davidkarlsen.com
http://mp3.davidkarlsen.com
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]