Spring Framework
  1. Spring Framework
  2. SPR-5439

"!target(...)" pointcut expression never matches any method

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.5.6
    • Fix Version/s: Waiting for Triage
    • Component/s: Core:AOP
    • Labels:
      None
    • Last commented by a User:
      false

      Description

      A pointcut expression containing

      !target(com.some.Interface)

      (note the negation in front!) never matches any method. Even if com.some.Interface doesn't have any implementations.

        Activity

        Hide
        Grzegorz Olędzki added a comment -

        The minimal example reproducing the problem.
        Run the com.syncron.using.spring.Main. The claim is the assert at the end should pass, but it fails.
        Removing the and !target(com.syncron.using.spring.DummyInterface) clause from pointcut expression makes the assertion pass.

        Show
        Grzegorz Olędzki added a comment - The minimal example reproducing the problem. Run the com.syncron.using.spring.Main. The claim is the assert at the end should pass, but it fails. Removing the and !target(com.syncron.using.spring.DummyInterface) clause from pointcut expression makes the assertion pass.
        Hide
        Andy Clement added a comment -

        Sorry I haven't gotten to this sooner.

        You must be very careful when using target() with an interface. This is because target considers the runtime types that will be around whilst the program is running. At runtime the object executing could be a subtype of whatever is specified and that subtype may implement the DummyInterface specified.

        In your case you want to intercept the method BeanImpl.logic(String). At runtime, due to method dispatching, the call could be executing in a class 'BeanImplSubType' whose definition is

        class BeanImplSubType extends BeanImpl implements DummyInterface {
        	public String logic(String s) {
        		return super.logic(s);
        	}
        }
        

        This is possible because you didn't specify that BeanImpl was final. If you had marked it final then AspectJ would have realised that no-one could subtype that and so DummyInterface could not be implemented by whatever type is running the logic() method at runtime, and in that case !target(DummyInterface) would match. But as it is written right now, !target(DummyInterface) does not entirely match statically and leaves behind a runtime check.

        If the entire program is translating to pure AspectJ and run, it will behave as expected because the runtime check about whether the instance executing the logic() method is a DummyInterface will determine it is not and call the advice. But in a Spring context, I'm not sure what happens to this runtime check. I ought to check with Ramnivas.

        Show
        Andy Clement added a comment - Sorry I haven't gotten to this sooner. You must be very careful when using target() with an interface. This is because target considers the runtime types that will be around whilst the program is running. At runtime the object executing could be a subtype of whatever is specified and that subtype may implement the DummyInterface specified. In your case you want to intercept the method BeanImpl.logic(String). At runtime, due to method dispatching, the call could be executing in a class 'BeanImplSubType' whose definition is class BeanImplSubType extends BeanImpl implements DummyInterface { public String logic( String s) { return super .logic(s); } } This is possible because you didn't specify that BeanImpl was final. If you had marked it final then AspectJ would have realised that no-one could subtype that and so DummyInterface could not be implemented by whatever type is running the logic() method at runtime, and in that case !target(DummyInterface) would match. But as it is written right now, !target(DummyInterface) does not entirely match statically and leaves behind a runtime check. If the entire program is translating to pure AspectJ and run, it will behave as expected because the runtime check about whether the instance executing the logic() method is a DummyInterface will determine it is not and call the advice. But in a Spring context, I'm not sure what happens to this runtime check. I ought to check with Ramnivas.
        Hide
        Jesse Orloff added a comment -

        This bug may be related to similar issue I have been having.

        When I have a compound pointcut expression in the form of:

        "target(something.Here) and !bean(somebean)"

        ["target(" from above can be replaced with "@target" or "@within" and possibly others (I have only tested these three). The "!" negation character can also be replaced with "not", and the two sub expressions can switch positions around the "and".]

        the expression always appears to evaluate to false. That is it never matches anything.

        It is a relatively significant issue for me that I can't use negation in my expressions when I use target, @target, or @within.

        Has there been any update to this particular bug?

        Show
        Jesse Orloff added a comment - This bug may be related to similar issue I have been having. When I have a compound pointcut expression in the form of: "target(something.Here) and !bean(somebean)" ["target(" from above can be replaced with "@target" or "@within" and possibly others (I have only tested these three). The "!" negation character can also be replaced with "not", and the two sub expressions can switch positions around the "and".] the expression always appears to evaluate to false. That is it never matches anything. It is a relatively significant issue for me that I can't use negation in my expressions when I use target, @target, or @within. Has there been any update to this particular bug?
        Hide
        Andy Clement added a comment -

        There hasn't been an update.

        Are you using an interface with target()? (and perhaps hitting issues around my previous comment)

        The bean designator is purely a spring extension - we have no AspectJ tests for it (but I'm sure there are spring ones). Do things behave if you simply use the bean piece? (i.e. don't use the target component). If it is the bean piece playing up then that is likely to be a new bug.

        Show
        Andy Clement added a comment - There hasn't been an update. Are you using an interface with target()? (and perhaps hitting issues around my previous comment) The bean designator is purely a spring extension - we have no AspectJ tests for it (but I'm sure there are spring ones). Do things behave if you simply use the bean piece? (i.e. don't use the target component). If it is the bean piece playing up then that is likely to be a new bug.
        Hide
        Jesse Orloff added a comment -

        I was using an interface when using target. But when I used @target and @within, I was using the annotations, which were applied to the implementation classes.

        However, I believe I have found a workaround. See below:

        within(@the.type.Annotation ) and !bean(notwanted)

        This appears to do what I need without using target. There may be other issues, but I have not seen them yet.

        Show
        Jesse Orloff added a comment - I was using an interface when using target. But when I used @target and @within, I was using the annotations, which were applied to the implementation classes. However, I believe I have found a workaround. See below: within(@the.type.Annotation ) and !bean(notwanted ) This appears to do what I need without using target. There may be other issues, but I have not seen them yet.
        Hide
        Jesse Orloff added a comment -

        Sorry, I forgot to mention. bean() works fine with or without negation. To see the other forum post I had about my issue specifically please view: http://forum.springsource.org/showthread.php?p=360460#post360460. I'm not sure the issues are exactly the same, but they seem pretty close...at least related.

        Show
        Jesse Orloff added a comment - Sorry, I forgot to mention. bean() works fine with or without negation. To see the other forum post I had about my issue specifically please view: http://forum.springsource.org/showthread.php?p=360460#post360460 . I'm not sure the issues are exactly the same, but they seem pretty close...at least related.
        Hide
        Chris Beams added a comment -

        Andy, please triage as time allows. De-scheduling from 3.1 RC1 until that is complete.

        Show
        Chris Beams added a comment - Andy, please triage as time allows. De-scheduling from 3.1 RC1 until that is complete.

          People

          • Assignee:
            Andy Clement
            Reporter:
            Grzegorz Olędzki
            Last updater:
            Chris Beams
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Days since last comment:
              2 years, 43 weeks ago