Results 1 to 8 of 8

Thread: is AOP preferred for Logging ?

  1. #1
    Join Date
    Sep 2010
    Posts
    28

    Question is AOP preferred for Logging ?

    In many blogs we can find examples of logging using @Aspectj(AOP).
    Spring document states
    1. Any given pointcut will be matched against public methods only.
    2. We recommend the use of the Spring 2.0 and later AOP support(annotation based @Aspectj)

    1. My question is whether it is recommended approach to use AOP for logging purpose?
    2. If yes then how to create pointcuts which matches Protected/private members of the class?

  2. #2
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    1. My question is whether it is recommended approach to use AOP for logging purpose?
    Yes, it is. Logging itself is an aspect that cross-cuts all the components of an application and is independent from application functionality. As such, it is a perfect candidate for being managed by AOP. In fact, as you already stated, it's the classical example brought when explaining how AOP works.

    2. If yes then how to create pointcuts which matches Protected/private members of the class?
    You will need to use a full-blown AOP framework like AspectJ for that. Spring AOP, as explained in the documentation, is proxy-based. This is its main strenght and also its main weakness: the strenght comes from the easiness of installation and use: a couple of configuration lines in xml and a simple java class with 2-3 annotations is all you need to make it work. The weakness comes from the limitations of proxy-based AOP: logically static methods, private methods, and also public methods that are called internally from the class itself, cannot be advised.
    In turn, a full-blown AOP solution like AspectJ fully overcomes this limitations, but at the cost of increased configuration complexity and need for external tools. Luckily, Spring besides providing its own AOP also provides full support for AspectJ if you need to use it. Read the reference guide.

  3. #3
    Join Date
    Sep 2010
    Posts
    28

    Default

    http://static.springsource.org/sprin...roduction-defn

    As advised in previous reply i tried aspectj(full-blown AOP solution) by referring the springs documentation.

    Code:
    package com.mycompany.log;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class GeneralLogger {
    	private LogCreation log = null;
    	
    	public GeneralLogger() {
    		System.out.println("GeneralLogger");
    		log = new LogCreation();//creates instance of logger
    	}
    	
    	@SuppressWarnings("unused")
    	@Pointcut("execution(*com.mycompany.*.*(..))")
    	private void publicMethods() {	}
    	
    	@Around( "execution(!private * com.mycompany.*.*(..))")	
    	public Object profile(ProceedingJoinPoint pjp) throws Throwable {
    		String methodName=pjp.getSignature().getName();
    		String className=pjp.getTarget().toString();
    		
    		long start = System.currentTimeMillis();
    		log.writeLogEntry("=>Beginning of "+methodName+" method of the class "+className);
    		Object output = pjp.proceed();
    		log.writeLogEntry("=>End of "+methodName+" method of the class "+className);
    		long elapsedTime = System.currentTimeMillis() - start;
    		log.writeLogEntry("=>Method execution time for the method "+methodName +" of the class "+ className+" is : "+ elapsedTime+ " milliseconds.");
    		return output;
    	}
    	
    	@AfterThrowing(pointcut="publicMethods()", throwing="ex" )
    	public void doRecoveryActions(Exception exception) {
    		log.writeErrorEntry("=>"+exception.getClass().toString() + " :: " + exception.getMessage());
    	}
    
    
    }

    in applicationContext.xml i have added the configuration
    Code:
    <aop:aspectj-autoproxy/>
        <bean id="errorLogger" class="com.mycompany.log.GeneralLogger" />
    i have even added pom dependencies
    Code:
    <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjrt</artifactId>
       <version>1.6.9</version>
    </dependency>
    <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.6.9</version>
    </dependency>
    but still advise is applied only to public methods not to protected methods(many important methods in spring batch are protected and we need to apply advise to those protected methods).

    please point out if i have missed anything

  4. #4
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    Yes, you missed something very important...with your configuration, you are actually using Spring AOP, not AspectJ! So it is normal that private methods don't get advised. Perhaps it is not very well specified in the documentation, but using @AspectJ annotation support means only doing Spring AOP with annotations that are like AspectJ annotations, instead of doing it with xml configuration (using the aop: namespace), it doesn't mean using AspectJ framework itself!
    As I specified earlier, using AspectJ is not as simple as a few xml lines and some annotations on a class...AspectJ works with either compile time weaving or load time weaving, both strategies require obviously more than simple java to run...for compile time weaving, you will have to compile your classes with the AspectJ compiler, for load time weaving, you will need to install a weaver in your application server...also, AspectJ is not Java, it is a different language! Please read the reference guide carefully...

  5. #5
    Join Date
    Mar 2011
    Location
    Conway, AR
    Posts
    12

    Default

    AOP is great for logging as explained by Enrico. Refer to this example if you are trying to get AspectJ integrated.

    If you have any problems post back here. I pulled my hair out when I decided to move to AspectJ from Spring AOP.

  6. #6
    Join Date
    Sep 2010
    Posts
    28

    Default

    note: My application is not a web application so doesn't contain any web container.I should run the application as executable jar

    Following the example in http://static.springsource.org/sprin...-first-example i have made some changes

    In applicationContext.xml
    Code:
    <context:load-time-weaver aspectj-weaving="on"/>
    Even tried with this
    <context:load-time-weaver weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
    In aop.xml
    Code:
    <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
    <aspectj>
    	<weaver>
    		<include within="com.mycompany.jobs.*" />
    	</weaver>
    	<aspects>
    		<aspect name="com.mycompany.util.GeneralLoggerAspect" />
    	</aspects>
    </aspectj>

    In my eclipse VM arguments I have added
    Code:
    -javaagent:C:\Documents and Settings\kamath\.m2\repository\org\aspectj\aspectjweaver\1.6.9\aspectjweaver-1.6.9.jar 
    -javaagent:C:\Documents and Settings\kamath\.m2\repository\org\springframework\spring-instrument\3.0.5.RELEASE\spring-instrument-3.0.5.RELEASE.jar
    I am getting the following error
    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.weaving.AspectJWeavingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:880)
    	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:533)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:362)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    	at com.mycompany.main.Start.main(Start.java:35)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)
    	at org.springframework.context.weaving.LoadTimeWeaverAwareProcessor.postProcessBeforeInitialization(LoadTimeWeaverAwareProcessor.java:85)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:350)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1331)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
    	... 14 more
    Caused by: java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    	at org.springframework.context.weaving.DefaultContextLoadTimeWeaver.setBeanClassLoader(DefaultContextLoadTimeWeaver.java:82)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1322)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
    	... 26 more
    Exception in thread "main" java.lang.NullPointerException
    	at com.mycompany.main(Start.java:71)
    Last edited by kamath_sv; Mar 25th, 2011 at 04:11 AM.

  7. #7
    Join Date
    Mar 2011
    Location
    Conway, AR
    Posts
    12

    Default

    Try to use the InstrumentationLoadTimeWeaver instead of the ReflectiveLTW (and use the spring-instrument.jar on the -javaagent flag). You only need to have the spring-instrument.jar passed in, the aspectjweaver.jar is not needed.

    And have you tried running your JAR manually on the command-line? If not, try that too.

    Also, just a heads up... but you don't have to specify the aspectj-weaving attribute in the load-time-weaver element in applicationContext. As stated in the documentation for the load-time-weaver element:

    The activation of AspectJ load-time weaving is specified via a simple flag (the 'aspectj-weaving' attribute), with the AspectJ class transformer registered through Spring's LoadTimeWeaver. AspectJ weaving will be activated by default if a "META-INF/aop.xml" resource is present in the classpath.
    Last edited by damrass; Mar 25th, 2011 at 09:44 AM.

  8. #8
    Join Date
    Sep 2010
    Posts
    28

    Default

    Due to time constraints i have dropped the plan to use AOP instead of traditional way of logging for time being. Will revisit this soon.

    My requirement is : in many places i will be executing the queries, in traditional(currently using) approach i can easily add log statements in any place i want. I want to log say, all the queries generated by application.

    With my limited knowledge i know AOP has before,after & around advice & using those advice we cannot add log statements between the method where queries are executed.

    Does AOP satisfy this requirement ?
    Is there any way in AOP to get solution for my problem?
    I hope this is common requirement in logging.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •