Announcement Announcement Module
Collapse
No announcement yet.
Schema-based AOP: advice not executed Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Schema-based AOP: advice not executed

    Hello,

    I am going nuts: I am new and just want to implement a simple profiler within my app that is basically based on that from the Spring docs.

    First:
    - I use Java 1.5
    - Spring is 2 RC3
    - I regard pointcuts as part of my config, so they reside within my XML file
    - all my implementations are based on interfaces
    - features of AspectJ not required

    So, I just want all methods of my implementations to cause invokation of a profiler method. My config looks like this:

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xmlns:aop="http://www.springframework.org/schema/aop"
    	   xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    	<bean
    		id="profiler"
    		class="my.package.SimpleProfiler"
    	/>
    
    	<aop:config>
    		<aop:aspect id="profiling" ref="profiler">
    		    <aop:around 
          			pointcut="execution(* my.package.*.*(..))" 
          			method="profile"
          		/>
    		</aop:aspect>
    	</aop:config>
    
    [...]
    
    </beans>
    This is the SimpleProfiler implementation:
    Code:
    package my.package;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.springframework.util.StopWatch;
    
    public class SimpleProfiler {
    
    	public Object profile(ProceedingJoinPoint call) throws Throwable {
    		System.out.println("Profiler");
    	      StopWatch clock = new StopWatch(
    	            "Profiling...");
    	      try {
    	         clock.start(call.toShortString());
    	         return call.proceed();
    	      } finally {
    	         clock.stop();
    	         System.out.println(clock.prettyPrint());
    	      }
    	   }
    
    }
    As said, straight from the Spring docs. However, whatever pointcuts I try, nothing happens, although I invoke methods from my implementations - all created by the Spring container. Additionally, the AOP config is parsed; so if I do errors in aop: elements or their attribute names, I get an exception.

    Do I have to activate AOP somewhere? I have read the docs and forums quite some times but fail to get a solution. Also, as you see my pointcut is quite general - do I have to name interfaces there? Although I have interfaces, I do not know if this bytecode modification stuff applies here...

    Thanks and regards,
    Timo

    P.S.: this is no web-app but a simple standalone app launched from a shell

  • #2
    The code itself seems alright. The only suspect is the pointcut itself (and due to removed code for bean definitions, it is not possible to give a definitive answer).

    My suggestion is that you relax the pointcut definition to "execution(* *(..))". This will select more join points than you need, but it will give a good starting point.

    -Ramnivas

    Comment


    • #3
      Hello ramnivas,

      Thanks for the reply. I forgot to mention that this was exactly what I have tried before posting, namely to relax pointcut expressions. But good to know that code seems alright.

      Thanks and regards,
      Timo

      Comment


      • #4
        Perhaps, you can post a small complete project to help track down the problem.

        -Ramnivas

        Comment


        • #5
          Rehi,

          Well, I would but it is really hard to prepare, because I modularised it into several Jars that I would have to decompose.

          But perhaps another question of design - I had this in mind in order to use AOP:

          There is a central class instance in my application that ALL objects need a reference to - and that before any methods or properties of them are called/invoked.

          So, one solution would be by using Spring IoC: for every bean created, I could set that instance using a property (so a ref to that central object). Tradeoffs:
          - I have to to that property for every bean, much redundancy
          - access order problem: setters of these beans invoked through the IoC container already require access to central object and thus fail (null pointer)

          The other solution would be to use Spring IoC again, now providing access to this central instance by passing it to each bean as constructor argument. Tradeoffs:
          - Again, too much redundancy
          - My app implements interfaces and as these constructors become vital part of the inner workings, it is not nice that I cannot declare these required constructors in my interface declarations, e.g. public AnyBean(Object centralObj);

          Is AOP the right solution for this kind of automatism? In my view, it is a central aspect that each bean receives a reference to a central object just after their creation.
          But I suppose, there is the problem that I cannot declare pointcuts for constructors, or? So, this aspect would always have to execute exactly after each constructor of any object in order to call a setter publishing my central implementation...

          I hope I made my problem clear ;-)

          Thanks and regards,
          Timo

          Comment


          • #6
            Timo, I wonder if a mixin interface would be the easiest solution to your problem. Suppose you have an interface:

            Code:
            public interface CentralObjectLocator()
            {
               CentralObject getCentralObject();
            }
            If I remember correctly, you can use the pointcut language to mix this interface into a large swath of your services at once. Only the implementation of this interface would have to be injected with CentralObject. This would keep you from having to configure each and every service to be injected with CentralObject.

            Comment


            • #7
              Hello cepage,

              ...but this would require full AspectJ integration (compiler), because this would do bytecode modifications, or?

              Thanks,
              Timo

              p.s. sorry, just exploring AOP as such ;-)

              Comment


              • #8
                No, I don't believe AspectJ is necessary, as long as you are only introducing the interface to Spring-managed services. Mixins have been supported back to Spring 1.x.

                Section 7.3.2.5 of the current docs gives an example.

                Comment


                • #9
                  Rehi Corby,

                  now I am a bit unsure after having read the named chapter and you first posting again. At least, perhaps I have fulfilled one of the requirements.

                  I have a basic interface that defines setter and getter for CentralObject. Also, I have a basic object that implements this interface. Each and every object is inherits from this basic objects in some way, because each objects extends other classes that at some point go down to this basic object (besides implementing other interfaces).

                  So I am stucking at this sentence written by you:
                  "Only the implementation of this interface would have to be injected with CentralObject"

                  So, this injection is done by the mixin technique also or is it just the addition of interfaces? Sorry for asking such elementary questions, I am just on my way to find the easiest way to publish a bean to any other bean in a central way just after its creation ;-)

                  Thanks,
                  Timo

                  Comment


                  • #10
                    Let's use the naming I defined above for the sake of discussion.

                    My understanding of your problem is as follows. You have a very large number of classes that need access to CentralObject, defined elsewhere. Without AOP, here are two approaches:
                    • Inheritance. All of your classes extend CentralObjectLocatorBean, which knows how to get the reference to your CentralObject. This is very ugly, because the extends declarations need to be properly set up all over your code, and because it complicates any other inheritance hierarchies that may exist in your code.
                    • Injection. All of your classes are configured to inject CentralObject as a dependency. Still not all that desirable. You will be copying and pasting setCentralObject() all over your code, and you may have to copy and paste the dependency configuration all through your spring context files.
                    Using a mixin provides a third alternative. You can tell Spring that all of your services implement CentralObjectLocator, but none of your services actually have to implement the interface. Instead, any of your services will be able to access the interface on demand, by casting the service proxy to CentralObjectLocator, and retrieving the CentralObject on demand.

                    This sort of approach might be useful if CentralObject is actually used by, say, 20% of your services. Then only the services that actually need CentralObject have to do the casting, and the rest can remain blissfully unaware.

                    If you are actually in a situation where 100% of your services need CentralObject, then you may just want to use the injection solution, because casting to the mixin interface may not be any less onerous than configuring the injection.

                    Comment


                    • #11
                      Rehi Corby,

                      Ja, I have (and require) the "100% solution". However, I was mean enough not to tell of a joker I have: all my Spring IoC config is being generated thru XSLT from another generic format, thus I can cover the redundancy using the XSL template in combination with XSL parameters.

                      So, first hand, I will most probably stick to the injection method - still having the problem that I have to use constructor instead of setter due to "calling order" problems...

                      VERY big thanks to you! I'll stick to that AOP stuff however.
                      Just as a sidenode: in German Wikipedia, the author(s) tell that AOP might also be suitable to replace existing event mechanismens by using AOP in order to have less event-interface dependnencies etc. As we are creating a project depending on Human Interface Decives (HID, e.g. joystick), using AOP for "doing events" sounds interesting. I'll try further ;-)

                      Thanks and regards,
                      Timo

                      Comment

                      Working...
                      X