Announcement Announcement Module
Collapse
No announcement yet.
Custom Annotation Processing Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Custom Annotation Processing

    Hi,

    I would like to be able to annotate my services with a custom annotation, and run some AOP-like code only on those methods. I know I can do this with standard AOP and @Apsect annotations, but instead of defining in the aspect itself (or xml) which methods will be intercepted, I want to define it in every method I need, to have more visibility when coding and reviewing/code maintenance.

    An example would be to perform some lock checking on specific methods. I would like to do the following

    @Lockable
    public void performBankTransaction(....)

    And because that method is annotated with @Lockable, execute some code before it (that would lock based on some condition).

    As a super bonus, I would also like to be able to annotate a parameter in the method to control concurrency, like so:

    @Lockable
    public void performBankTransaction(@LockId Account from, Account to)

    would lock on the method using the 'from' field only (and my code knows how to lock based on that).

    I tried doing some searches for this but I'm having a hard time figuring out the correct keywords, as "annotations" / custom AOP etc lead me to all the standard pages.

    Any help would be much appreciated
    Thanks in advance
    AB

  • #2
    This should be really easy to implement. You need a pointcut such as:
    Code:
    execution(@com.myco.Loackable * *(..))
    and advise it to perform the locking logic.

    -Ramnivas

    Comment


    • #3
      Thanks!

      Thanks! that seems pretty easy, I thought I needed to do some pointcut based on interface name (like *Service) which I didn't particularly like. This is exactly what I wanted.

      Is there any way to get the @LockId parameter annotation inside the interceptor? (I want the instance object that has that annotation).

      Thanks in advance,
      AB

      Comment


      • #4
        Getting the argument with @LockId requires the use of reflection. You will need code such as the following:

        Code:
        @Before("lockOperation()")
        public void lock(JoinPoint jp) {
           Method m = ((MethodSignature)jp).getMethod();
           Annotation[][] paramAnnots = m.getParameterAnnotations();
           ... now check which paramAnnot is @LockId, 
           ... that will give you the index, 
           ... then grab the parameter by jp.getArgs()[index]
        }
        -Ramnivas

        Comment


        • #5
          Sounds Perfect. I will try it and let the forum know.

          Sincerely,
          AB

          Comment


          • #6
            ClassCastException

            Apparently I cannot cast the JoinPoint to the MethodSignature interface. I've debugged the code and I'm getting a MethodInvocationProceedingJoinPoint which only implements the ProceedingJoinPoint, JoinPoint.StaticPart interfaces, none of which extends MethodSignature.

            The exact error is
            java.lang.ClassCastException: org.springframework.aop.aspectj.MethodInvocationPr oceedingJoinPoint cannot be cast to org.aspectj.lang.reflect.MethodSignature

            I've been looking at available methods and I cannot find any other that can be used to get the Method class (or actually the @Annotation used in the class).

            As always any help is much appreciated
            Regards
            AB

            Comment


            • #7
              I missed getSignagure().. try the following:
              Code:
              Method m = ((MethodSignature)jp.getSignature()).getMethod();
              -Ramnivas

              Comment


              • #8
                Worked like a charm, silly me.

                The only issue I had is that this method is an implementation of an interface method, and I'm getting the interface's Method class instead of the implementation ones.

                I eventually did something like this (with pretty formatting)

                jp.getTarget().getClass().getMethod(m.getName(), m.getParameterTypes())

                Thanks for all your help pal
                Regards
                AB

                Comment

                Working...
                X