You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sirona.apache.org by rm...@apache.org on 2013/11/25 11:01:03 UTC

svn commit: r1545199 - in /incubator/sirona/trunk/agent: javaagent/ javaagent/src/main/java/org/apache/sirona/javaagent/ javaagent/src/test/java/org/apache/sirona/javaagent/ javaagent/src/test/java/org/apache/test/sirona/javaagent/ performance/aop/src/...

Author: rmannibucau
Date: Mon Nov 25 10:01:03 2013
New Revision: 1545199

URL: http://svn.apache.org/r1545199
Log:
SIRONA-10 better javaagent handling exceptions

Added:
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java
      - copied, changed from r1545191, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentCounter.java
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
      - copied, changed from r1545191, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/CounterAdvisor.java
Removed:
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentCounter.java
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/CounterAdvisor.java
Modified:
    incubator/sirona/trunk/agent/javaagent/pom.xml
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java
    incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java
    incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java
    incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java
    incubator/sirona/trunk/agent/performance/jaxrs/cxf/src/main/java/org/apache/sirona/agent/jaxrs/cxf/CxfJaxRsPerformanceHandler.java
    incubator/sirona/trunk/agent/performance/jaxrs/jaxrs2/src/main/java/org/apache/sirona/agent/jaxrs/jaxrs2/PerformanceServerFilter.java
    incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java

Modified: incubator/sirona/trunk/agent/javaagent/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/pom.xml?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/pom.xml (original)
+++ incubator/sirona/trunk/agent/javaagent/pom.xml Mon Nov 25 10:01:03 2013
@@ -32,7 +32,7 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.sirona</groupId>
-      <artifactId>sirona-core</artifactId>
+      <artifactId>sirona-aop</artifactId>
     </dependency>
     <dependency>
       <groupId>org.ow2.asm</groupId>

Copied: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java (from r1545191, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentCounter.java)
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java?p2=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java&p1=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentCounter.java&r1=1545191&r2=1545199&rev=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentCounter.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java Mon Nov 25 10:01:03 2013
@@ -17,42 +17,37 @@
 package org.apache.sirona.javaagent;
 
 import org.apache.sirona.Role;
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
 import org.apache.sirona.counters.Counter;
-import org.apache.sirona.repositories.Repository;
-import org.apache.sirona.stopwatches.StopWatch;
 
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-// just a helper to ease ASM work
-public class AgentCounter {
-    private final StopWatch watch;
+// just a helper to ease ASM work and reuse AbstractPerformanceInterceptor logic
+public class AgentPerformanceInterceptor extends AbstractPerformanceInterceptor<String> {
     private static final ConcurrentMap<String, Counter.Key> KEYS = new ConcurrentHashMap<String, Counter.Key>();
 
-    public AgentCounter(final StopWatch watch) {
-        this.watch = watch;
+    public static void initKey(final String name) {
+        KEYS.putIfAbsent(name, new Counter.Key(Role.PERFORMANCES, name));
     }
 
     // called by agent
-    public static AgentCounter start(final String name) {
-        final Counter.Key key = findKey(name);
-        final Counter monitor = Repository.INSTANCE.getCounter(key);
-        return new AgentCounter(Repository.INSTANCE.start(monitor));
+    public static Context start(final String name) {
+        return new AgentPerformanceInterceptor().before(name, name);
     }
 
-    private static Counter.Key findKey(final String name) {
-        final Counter.Key found = KEYS.get(name);
-        if (found != null) {
-            return found;
-        }
-
-        final Counter.Key key = new Counter.Key(Role.PERFORMANCES, name);
-        KEYS.putIfAbsent(name, key);
-        return key;
+    @Override
+    protected Counter.Key getKey(final String name) {
+        return KEYS.get(name);
     }
 
-    // called by agent
-    public void stop() {
-        watch.stop();
+    @Override
+    protected Object proceed(final String invocation) throws Throwable {
+        throw new UnsupportedOperationException("shouldn't be called directly");
+    }
+
+    @Override
+    protected String getCounterName(final String invocation) {
+        return invocation;
     }
 }

Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java Mon Nov 25 10:01:03 2013
@@ -64,20 +64,19 @@ public class SironaAgent {
         private byte[] doTransform(final String className, final byte[] classfileBuffer) {
             final ClassReader reader = new ClassReader(classfileBuffer);
             final ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-            final CounterAdvisor advisor = new CounterAdvisor(writer, className);
+            final SironaClassVisitor advisor = new SironaClassVisitor(writer, className);
             reader.accept(advisor, ClassReader.SKIP_DEBUG);
             return writer.toByteArray();
         }
 
         private boolean shouldTransform(final String className) {
-            if (className.startsWith("sun/")
-                || className.startsWith("com/sun/")
-                || className.startsWith("java/")
-                || className.startsWith("org/apache/sirona")) {
-                return false;
-            }
+            return !( // internals exclusions
+                     className.startsWith("sun/")
+                  || className.startsWith("com/sun/")
+                  || className.startsWith("java/")
+                  || className.startsWith("org/apache/sirona")
+                ) && evaluator.matches(className.replace("/", "."));
 
-            return evaluator.matches(className.replace("/", "."));
         }
     }
 }

Copied: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java (from r1545191, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/CounterAdvisor.java)
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java?p2=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java&p1=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/CounterAdvisor.java&r1=1545191&r2=1545199&rev=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/CounterAdvisor.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java Mon Nov 25 10:01:03 2013
@@ -16,24 +16,27 @@
  */
 package org.apache.sirona.javaagent;
 
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
-import org.objectweb.asm.commons.AdviceAdapter;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+
+import java.lang.reflect.Modifier;
+
+public class SironaClassVisitor extends ClassVisitor implements Opcodes {
+    private static final String STATIC_INIT = "<clinit>";
+    private static final String CONSTRUCTOR = "<init>";
+    private static final String METHOD_SUFFIX = "_$_$irona_$_internal_$_original_$_";
 
-/**
- * TODO:
- * 1) create in transformed class constant for Counter.Keys
- * 2) avoid AgentCounter usage
- */
-public class CounterAdvisor extends ClassVisitor implements Opcodes {
-    public static final String AGENT_COUNTER = AgentCounter.class.getName().replace(".", "/");
     private final String javaName;
-    private boolean isInterface;
+    private Type classType;
 
-    public CounterAdvisor(final ClassWriter writer, final String javaName) {
+    public SironaClassVisitor(final ClassWriter writer, final String javaName) {
         super(ASM4, writer);
         this.javaName = javaName;
     }
@@ -42,46 +45,134 @@ public class CounterAdvisor extends Clas
     public void visit(final int version, final int access, final String name,
                       final String signature, final String superName, final String[] interfaces) {
         cv.visit(version, access, name, signature, superName, interfaces);
-        isInterface = (access & ACC_INTERFACE) != 0;
+        classType = Type.getType("L" + name.replace('.', '/') + ";");
     }
 
     @Override
     public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
-        final MethodVisitor delegate = cv.visitMethod(access, name, desc, signature, exceptions);
-        if (!isInterface) {
-            final String label = label(javaName, name, desc, exceptions);
-            return new SironaMethodVisitor(delegate, label, access, name, desc);
+        final MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
+        if (!isSironable(access, name)) {
+            return methodVisitor;
+        }
+
+        final String label = javaName.replace("/", ".") + "." + name;
+        AgentPerformanceInterceptor.initKey(label);
+
+        { // generate "proxy" method
+            final SironaMethodVisitor sironaVisitor = new SironaMethodVisitor(methodVisitor, label, access, new Method(name, desc), classType);
+            sironaVisitor.visitCode();
+            sironaVisitor.visitEnd();
         }
-        return delegate;
+
+        // generate internal method - the proxy (previous one) delegates to this one
+        return super.visitMethod(forcePrivate(access), name + METHOD_SUFFIX, desc, signature, exceptions);
+    }
+
+    private int forcePrivate(final int access) {
+        return (access & ~(Modifier.PRIVATE | Modifier.PUBLIC | Modifier.PROTECTED)) | Modifier.PRIVATE;
     }
 
-    private String label(final String className, final String methodName, final String desc, final String[] ex) {
-        return className.replace("/", ".") + "." + methodName;
+    private boolean isSironable(final int access, final String name) {
+        return !name.equals(STATIC_INIT) && !name.equals(CONSTRUCTOR)
+            && !Modifier.isAbstract(access) && !Modifier.isNative(access);
     }
 
-    private static class SironaMethodVisitor extends AdviceAdapter {
+    private static class SironaMethodVisitor extends GeneratorAdapter {
+        // types
+        private static final Type AGENT_COUNTER = Type.getType(AgentPerformanceInterceptor.class);
+        private static final Type CONTEXT_TYPE = Type.getType(AbstractPerformanceInterceptor.Context.class);
+        private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
+        private static final Type STRING_TYPE = Type.getType(String.class);
+        private static final String CONTEXT_NAME = CONTEXT_TYPE.getDescriptor();
+
+        // methods
+        private static final String START_METHOD = "start";
+        private static final String STOP_WITH_EXCEPTION_METHOD = "stopWithException";
+        private static final String STOP_METHOD = "stop";
+
         private final String label;
-        private int agentIdx;
+        private final boolean isStatic;
+        private final Type clazz;
+        private final boolean isVoid;
+        private final Method method;
 
         public SironaMethodVisitor(final MethodVisitor methodVisitor, final String label,
-                                    final int access, final String name, final String desc) {
-            super(ASM4, methodVisitor, access, name, desc);
+                                   final int access, final Method method, final Type clazz) {
+            super(ASM4, methodVisitor, access, method.getName(), method.getDescriptor());
             this.label = label;
+            this.clazz = clazz;
+            this.method = method;
+            this.isStatic = Modifier.isStatic(access);
+            this.isVoid = Type.VOID_TYPE.equals(method.getReturnType());
         }
 
         @Override
-        public void onMethodEnter() {
-            agentIdx = newLocal(Type.getType(AgentCounter.class));
-            mv.visitCode();
-            mv.visitLdcInsn(label);
-            mv.visitMethodInsn(INVOKESTATIC, AGENT_COUNTER, "start", "(Ljava/lang/String;)L" + AGENT_COUNTER + ";");
-            mv.visitVarInsn(ASTORE, agentIdx);
+        public void visitCode() {
+            final int agentIdx = newLocal(CONTEXT_TYPE);
+            push(label);
+            invokeStatic(AGENT_COUNTER, new Method(START_METHOD, "(" + STRING_TYPE + ")" + CONTEXT_NAME));
+            storeLocal(agentIdx);
+
+            final Label tryStart = mark();
+
+            invoke();
+
+            // store result to return it later if it doesn't return void
+            final int result = storeResult();
+
+            // take metrics before returning
+            loadLocal(agentIdx);
+            invokeVirtual(CONTEXT_TYPE, new Method(STOP_METHOD, "()V"));
+
+            // return result
+            returnResult(result);
+
+            final Label tryEnd = mark();
+            catchException(tryStart, tryEnd, THROWABLE_TYPE);
+
+            // context.stopWithException(throwable);
+            final int throwableId = newLocal(THROWABLE_TYPE);
+            storeLocal(throwableId);
+            loadLocal(agentIdx);
+            loadLocal(throwableId);
+            invokeVirtual(CONTEXT_TYPE, new Method(STOP_WITH_EXCEPTION_METHOD, Type.getType(Void.TYPE), new Type[]{THROWABLE_TYPE}));
+
+            // rethrow throwable
+            loadLocal(throwableId);
+            throwException();
+
+            endMethod();
         }
 
-        @Override
-        public void onMethodExit(final int opcode) {
-            mv.visitVarInsn(ALOAD, agentIdx);
-            mv.visitMethodInsn(INVOKEVIRTUAL, AGENT_COUNTER, "stop", "()V");
+        private void invoke() {
+            final Method mtd = new Method(method.getName() + METHOD_SUFFIX, method.getDescriptor());
+            if (isStatic) {
+                loadArgs();
+                invokeStatic(clazz, mtd);
+            } else {
+                loadThis();
+                loadArgs();
+                invokeVirtual(clazz, mtd);
+            }
+        }
+
+        private int storeResult() {
+            final int result;
+            if (!isVoid) {
+                result = newLocal(method.getReturnType());
+                storeLocal(result);
+            } else {
+                result = -1;
+            }
+            return result;
+        }
+
+        private void returnResult(int result) {
+            // return
+            if (!isVoid) {
+                loadLocal(result);
+            }
+            returnValue();
         }
     }
 }

Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java Mon Nov 25 10:01:03 2013
@@ -21,6 +21,7 @@ import org.junit.runner.JUnitCore;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
 import org.junit.runners.model.Statement;
 
@@ -83,7 +84,10 @@ public class JavaAgentRunner extends Blo
                 } catch (final Exception e) {
                     notifier.fireTestFailure(new Failure(description, e));
                 } finally {
-                    notifier.fireTestFinished(description);
+                    // little hack to get the right test number in surefire
+                    for (final FrameworkMethod mtd : getChildren()) {
+                        notifier.fireTestFinished(describeChild(mtd));
+                    }
                 }
             }
         };

Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java Mon Nov 25 10:01:03 2013
@@ -24,20 +24,26 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 @RunWith(JavaAgentRunner.class)
 public class SimpleTest {
     @Test
-    public void counters() {
+    public void noReturn() {
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.noReturn", 0);
-
         new ServiceTransform().noReturn();
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.noReturn", 1);
+    }
 
+    @Test
+    public void withReturn() {
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.withReturn", 0);
         new ServiceTransform().withReturn();
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.withReturn", 1);
+    }
 
+    @Test
+    public void nested() {
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.nest", 0);
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$Service2Transform.nested", 0);
         new ServiceTransform().nest();
@@ -45,7 +51,38 @@ public class SimpleTest {
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$Service2Transform.nested", 1);
     }
 
-    private void assertHits(final String name, final int expected) {
+    @Test
+    public void exception() {
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.exception", 0);
+        try {
+            new ServiceTransform().exception();
+            fail();
+        } catch (final IllegalArgumentException iae) {
+            // OK
+        }
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.exception", 1);
+        assertException(1, IllegalArgumentException.class);
+    }
+
+    @Test
+    public void alreadyTryCatch() {
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.alreadyTryCatch", 0);
+        new ServiceTransform().alreadyTryCatch();
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.alreadyTryCatch", 1);
+        assertException(0, NullPointerException.class);
+    }
+
+    private static void assertException(final int count, final Class<?> exception) {
+        int iae = 0;
+        for (final Counter c : Repository.INSTANCE.counters()) {
+            if (c.getKey().getName().contains(exception.getName())) {
+                iae++;
+            }
+        }
+        assertEquals(count, iae);
+    }
+
+    private static void assertHits(final String name, final int expected) {
         assertEquals(expected, Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, name)).getHits());
     }
 
@@ -61,6 +98,18 @@ public class SimpleTest {
         public String nest() {
             return new Service2Transform().nested();
         }
+
+        public void exception() {
+            throw new IllegalArgumentException();
+        }
+
+        public void alreadyTryCatch() {
+            try {
+                throw new NullPointerException();
+            } catch (final NullPointerException iae) {
+                // no-op
+            }
+        }
     }
 
     public static class Service2Transform {

Modified: incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java (original)
+++ incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java Mon Nov 25 10:01:03 2013
@@ -17,8 +17,8 @@
 
 package org.apache.sirona.aop;
 
-import org.apache.sirona.SironaException;
 import org.apache.sirona.Role;
+import org.apache.sirona.SironaException;
 import org.apache.sirona.configuration.Configuration;
 import org.apache.sirona.counters.Counter;
 import org.apache.sirona.repositories.Repository;
@@ -87,7 +87,11 @@ public abstract class AbstractPerformanc
             error = t;
             throw t;
         } finally {
-            ctx.stop(error);
+            if (error == null) {
+                ctx.stop();
+            } else {
+                ctx.stopWithException(error);
+            }
         }
     }
 
@@ -96,7 +100,7 @@ public abstract class AbstractPerformanc
 
         final StopWatch stopwatch;
         if (context.shouldExecute()) {
-            final Counter monitor = Repository.INSTANCE.getCounter(new Counter.Key(getRole(), name));
+            final Counter monitor = Repository.INSTANCE.getCounter(getKey(name));
             stopwatch = Repository.INSTANCE.start(monitor);
         } else {
             stopwatch = null;
@@ -105,6 +109,10 @@ public abstract class AbstractPerformanc
         return new Context(context, stopwatch);
     }
 
+    protected Counter.Key getKey(final String name) {
+        return new Counter.Key(getRole(), name);
+    }
+
     protected boolean isAdaptive() {
         return ADAPTIVE;
     }
@@ -173,7 +181,7 @@ public abstract class AbstractPerformanc
     /**
      * The handler for cases where interception is not possible and you need to pass the "before"object to be able to monitor.
      */
-    protected static class Context {
+    public static class Context {
         private final ActivationContext activationContext;
         private final StopWatch stopWatch;
 
@@ -182,7 +190,14 @@ public abstract class AbstractPerformanc
             this.stopWatch = stopWatch;
         }
 
-        public void stop(final Throwable error) {
+        public void stop() {
+            if (stopWatch != null) {
+                final long elapsedTime = stopWatch.stop().getElapsedTime();
+                activationContext.elapsedTime(elapsedTime);
+            }
+        }
+
+        public void stopWithException(final Throwable error) {
             if (stopWatch != null) {
                 stopWatch.stop();
 

Modified: incubator/sirona/trunk/agent/performance/jaxrs/cxf/src/main/java/org/apache/sirona/agent/jaxrs/cxf/CxfJaxRsPerformanceHandler.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jaxrs/cxf/src/main/java/org/apache/sirona/agent/jaxrs/cxf/CxfJaxRsPerformanceHandler.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/performance/jaxrs/cxf/src/main/java/org/apache/sirona/agent/jaxrs/cxf/CxfJaxRsPerformanceHandler.java (original)
+++ incubator/sirona/trunk/agent/performance/jaxrs/cxf/src/main/java/org/apache/sirona/agent/jaxrs/cxf/CxfJaxRsPerformanceHandler.java Mon Nov 25 10:01:03 2013
@@ -48,7 +48,7 @@ public class CxfJaxRsPerformanceHandler 
     public Response handleResponse(final Message m, final OperationResourceInfo ori, final Response response) {
         final Context context = Context.class.cast(m.getExchange().get(PROP_KEY));
         if (context != null) {
-            context.stop(null);
+            context.stop();
         }
         return null;
     }

Modified: incubator/sirona/trunk/agent/performance/jaxrs/jaxrs2/src/main/java/org/apache/sirona/agent/jaxrs/jaxrs2/PerformanceServerFilter.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jaxrs/jaxrs2/src/main/java/org/apache/sirona/agent/jaxrs/jaxrs2/PerformanceServerFilter.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/performance/jaxrs/jaxrs2/src/main/java/org/apache/sirona/agent/jaxrs/jaxrs2/PerformanceServerFilter.java (original)
+++ incubator/sirona/trunk/agent/performance/jaxrs/jaxrs2/src/main/java/org/apache/sirona/agent/jaxrs/jaxrs2/PerformanceServerFilter.java Mon Nov 25 10:01:03 2013
@@ -51,7 +51,7 @@ public class PerformanceServerFilter ext
     public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException {
         final Context context = Context.class.cast(requestContext.getProperty(SIRONA_PERFORMANCE_PROP));
         if (context != null) {
-            context.stop(null);
+            context.stop();
         }
     }
 

Modified: incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java?rev=1545199&r1=1545198&r2=1545199&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java (original)
+++ incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java Mon Nov 25 10:01:03 2013
@@ -57,7 +57,7 @@ public final class JPAProxyFactory {
             final Object o = doInvoke(new Invocation(instance, method, args));
             final Class<?> returnType = method.getReturnType();
             if (cascade && returnType.isInterface()) { // not java.*
-                return monitor(classes(returnType, o), o, role, cascade);
+                return monitor(classes(returnType, o), o, role, true);
             }
             return o;
         }