Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] Is @DeclareMixin + around advice supported?

Hello,

I would like to know whether it is supported to use @DeclareMixin & around advice in the way like below:
     public interface KeySetKeyLockHandler {
          // method signatures
     }
    
     public static class KeySetKeyLockHandlerImpl implements KeySetKeyLockHandler {
          // contents of class
     }
    
     @DeclareMixin( value="slingong.web.gae.TransactionalMemcacheServiceImpl")
     public static KeySetKeyLockHandler addKeySetKeyLockHandlerInterface( Object instance) {
          return new KeySetKeyLockHandlerImpl( (TransactionalMemcacheServiceImpl)instance);
     }
    
     @Around( value="execution( "
                              + "public * slingong.web.gae.TransactionalMemcacheServiceBase+"
                                   + ".setKeySetKey( java.lang.String)) "
                         + "&& this( keySetKeyLockHandler)"
               )
     public Object aroundAdvisedSetKeySetKeyMethodExecution(
               ProceedingJoinPoint proceedingJoinPoint, KeySetKeyLockHandler keySetKeyLockHandler) {
              
               // Do some works on keySetKeyLockHandler
              
               // Invocation of actual target method -------------------------------------------------
               try {
                    return proceedingJoinPoint.proceed( proceedingJoinPoint.getArgs());
               }
               catch( Throwable throwable) {
                    // Exception handling
               }
               // ------------------------------------------------------------------------------------
              
               // Do some works on keySetKeyLockHandler
     }
    
      Note: 
          KeySetKeyLockHandler interface does not contain the definition of the setKeySetKey method.
          TransactionalMemcacheServiceImpl class is extended from TransactionalMemcacheServiceBase abstract class

I abbreviated the details from the actual code for easier readability. 

What I expected was that, of course, calling the proceed method in the code snippet above executes setKeySetKey method of TransactionalMemcacheServiceImpl instance.
However, it fails at that statement by the puzzling ClassCastException like:
     slingong.web.gae.TransactionalMemcacheServiceException: java.lang.ClassCastException: java.lang.String cannot be cast to slingong.web.gae.TransactionalMemcacheServiceBase
          at slingong.web.gae.TransactionalMemcacheServiceBase.setKeySetKey_aroundBody1$advice(TransactionalMemcacheServiceBase.java:456)
          at slingong.web.gae.TransactionalMemcacheServiceBase.setKeySetKey_aroundBody2(TransactionalMemcacheServiceBase.java:1)
          at slingong.web.gae.TransactionalMemcacheServiceBase.setKeySetKey_aroundBody3$advice(TransactionalMemcacheServiceBase.java:578)
          at slingong.web.gae.TransactionalMemcacheServiceBase.setKeySetKey(TransactionalMemcacheServiceBase.java:132)
          at slingong.web.gae.TransactionalMemcacheServiceFactory.getInstance(TransactionalMemcacheServiceFactory.java:180)
          at slingong.web.gae.TransactionalMemcacheServiceFactoryTest.testGetInstance(TransactionalMemcacheServiceFactoryTest.java:93)

As you may notice from the stack trace above, I have 2 around-advices weaving at this join point, and as I said that I omitted the detail, that exception may not be caused of the usage of @DeclareMixin & around advice but from those omitted parts. However, I like to be sure about if it's supported usage before digging deeper to find the cause, since I do not feel so sure about calling ProceedingJoinPoint.proceed method after mixing even though I assumed that it would be OK because I could not have found any document to tell the restriction on such combination.

I ran the test code under debugger and found that it fails at the statement calling proceed method right after getArgs method returns before actually running target setKeySetKey method.
Just before throwing the exception, proceedingJoinPoint appeared as below in debugger (though I eliminated the info on TransactionalMemcacheServiceImpl fields because I thought those would just bloated lines of info without clue.) It appears to me that the proceedingJoinPoint seems to be expected...

proceedingJoinPoint     JoinPointImpl  (id=49)    
     _this     TransactionalMemcacheServiceImpl  (id=44)    
          $SWITCH_TABLE$com$google$appengine$api$memcache$MemcacheService$SetPolicy     null    
          ajc$anno$0     null    
          ajc$aspectjutil_eventmanager_EventListenerInstanceTracker$ptwAspectInstance     EventListenerInstanceTracker  (id=55)    
               ajc$withinType     "slingong.web.gae.TransactionalMemcacheServiceBase" (id=106)    
               listenerMap     WeakHashMap<K,V>  (id=107)    
          ajc$aspectjutil_eventmanager_EventListenerInstanceTracker$ptwAspectInstance     EventListenerInstanceTracker  (id=72)    
               ajc$withinType     "slingong.web.gae.TransactionalMemcacheServiceImpl" (id=111)    
               listenerMap     WeakHashMap<K,V>  (id=112)    
          ajc$instance$slingong_web_gae_TransactionalMemcacheServiceBaseThreadSyncAspect$slingong_web_gae_TransactionalMemcacheServiceBaseThreadSyncAspect$KeySetKeyLockHandler     TransactionalMemcacheServiceBaseThreadSyncAspect$KeySetKeyLockHandlerImpl  (id=73)    
               transactionalMemcacheServiceImpl     TransactionalMemcacheServiceImpl  (id=44)    
     arc     null    
     args     Object[1]  (id=101)    
          [0]     "testGetInstance_keySetKey" (id=67)    
     staticPart     JoinPointImpl$StaticPartImpl  (id=103)    
          id     1    
          kind     "method-execution" (id=115)    
               count     16    
               hash     0    
               offset     0    
               value     (id=128)    
          signature     MethodSignatureImpl  (id=116)    
               EMPTY_CLASS_ARRAY     Class<T>[0]  (id=129)    
               EMPTY_STRING_ARRAY     String[0]  (id=131)    
               useCache     true    
               declaringType     Class<T> (slingong.web.gae.TransactionalMemcacheServiceBase) (id=43)    
               declaringTypeName     "slingong.web.gae.TransactionalMemcacheServiceBase" (id=106)    
               exceptionTypes     Class<T>[0]  (id=137)    
               lookupClassLoader     null    
               method     null    
               modifiers     1    
               name     "setKeySetKey" (id=138)    
               parameterNames     String[1]  (id=139)    
                    [0]     "newKeysSetKey" (id=141)    
               parameterTypes     Class<T>[1]  (id=140)    
                    [0]     Class<T> (java.lang.String) (id=68)    
               returnType     Class<T> (void) (id=142)    
               stringCache     SignatureImpl$CacheImpl  (id=143)    
                    toStringCacheRef     SoftReference<T>  (id=149)    
                         clock     1326542103609    
                         lock     Reference$Lock  (id=152)    
                         pending     null    
                         discovered     null    
                         next     null    
                         queue     ReferenceQueue$Null  (id=154)    
                         referent     String[3]  (id=157)    
                              [0]     "void slingong.web.gae.TransactionalMemcacheServiceBase.setKeySetKey(String)" (id=161)    
                              [1]     null    
                              [2]     null    
                         timestamp     1326542103609    
               stringRep     null    
          sourceLocation     SourceLocationImpl  (id=118)    
               fileName     "TransactionalMemcacheServiceBase.java" (id=162)    
               line     130    
               withinType     Class<T> (slingong.web.gae.TransactionalMemcacheServiceBase) (id=43)    
     target     TransactionalMemcacheServiceImpl  (id=44)     

Regards,
Art


Back to the top