Thursday 4 August 2011

AspectJ and Custom Logging Annotation

Ive been using AspectJ for a while now and find its got some really cool usages as well as your standard ones like Transaction Management etc. One of the projects Ive brecently been working on has a very ridged process going through the motions in a very structured and standardised way. Originally when I created the little application I always had a log statement at the beginning of the method simply stating its purpose and incoming method args. As this would be a simple JAR application deployed and run via a main method, this sort of logging is good to determine run times and at what point the application gets to. I had already used AOP in the project to profile and time some of the very long running operations which is when I thought of nicely hooking in AspectJ and method logging together.

What I have created is a simple custom logging annotation which when applied to a method on a spring managed bean will log out at the given level and print the method name and args invoked with.


Ive created a sample/demonstration project over on my GitHub which can found here. To see the loogin simple run the main method inside the demonstration project form GitHub.

Here is a usage demonstration of how an application can utilise the Logging annotation.



Simply annotate your method and when it gets invoke you will having logging such as this.

13:27:48.560 [main] DEBUG c.morgan.design.demo.LoggingExample - Method Invocation=[logMe] - Args=[]
13:27:48.561 [main] INFO  c.morgan.design.demo.LoggingExample - Method Invocation=[logMeInfoWithMethodArgs] - Args=[abcdefg, 1234]
13:27:48.561 [main] WARN  c.morgan.design.demo.LoggingExample - Method Invocation=[logMeWarningWithMethodArgs] - Args=[abcdefg, 1234, true]
13:27:48.573 [main] DEBUG c.morgan.design.demo.LoggingExample - Method Invocation=[logMeDebugWithMethodArgs] - Args=[abcdefg, 1234, false, 0.2]

This is only a sample project, If this was to be used in a more production ready application I'm pretty sure I would pick a better name. :)

This is how the demonstration Logging Aspect looks:

I've chosen to take an annotation based approach but this could also be done using XML configuration.



Enhancements to make would be:

* Instead of having three different methods for the various logging level, have only one and retrieve the annotation from the method and determine its logging level from the annotation value.
* At the moment this only supports log-back and log4j, this could be made more abstract and determine the logging libraries for each application.
* Make it in to a library project in which you could simple include the library and configure it. i.e. only log for particular methods, packages etc.
* Allow for custom logging pattern configuration.

Anyway, its a small simple sample of the power of AspectJ, all comments welcome as usual.

Agile @ 10 - Some interesting posts

Here are two posts which are very interesting about Agile's 10th anniversary from two of people who have experienced it all. Its interesting for me since I've only been doing it for 3 years and I see changes happening, what will be next.

Ten Years Of Agile: An Interview with Robert C. "Uncle Bob" Martin

Laurent Bossavit: Agile Ten Years On

Monday 1 August 2011

Issues Using Maven 2 Assembly Plugin & Spring

Friday evening I tried in vain to package up my deployable Spring JAR file using the standard maven assembly plugin using the given configuration as seen below with no luck. I kept getting hit by spring throwing exceptions when trying to run the JAR file as the spring.shemas and spring.handler files where incorrect. It seems that when maven builds the package, it keeps overwritting the shemas and handlers files and by the end of the build they are both missing elements.

Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 8 in XML document from class path resource [spring/spring-dataCleansing.xml] is
invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'beans'.


	maven-assembly-plugin
	
		
			jar-with-dependencies
		
			
				
					com.some.package.Main
				
			
			
			
				true
					
						
							META-INF/spring.handlers
								META-INF/spring.schemas
							
						
					
				
			
			
				
					make-assembly
					package
					
						attached
					
				
			
		

It turns out this is a known bug and quite well documented. See: http://jira.codehaus.org/browse/MASSEMBLY-360.
So I turned my attention to maven shade plugin to build and package my JAR file, this only worked straight away.

My final maven shade plugin configuration is as follows:


            org.apache.maven.plugins
            maven-shade-plugin
            1.4
            
                
                    package
                    
                        shade
                    
                    
                        
                            
                                com.some.package.Main
                            
                            
                                META-INF/spring.handlers
                            
                            
                                META-INF/spring.schemas
                            
                        
			
				
				*:*
					
						META-INF/*.SF
						META-INF/*.DSA
						META-INF/*.RSA
					
				
			
                    
                
            
        


Using org.apache.maven.plugins.shade.resource.AppendingTransformer allows for the shade plugin to merge all spring.schemas and spring.handlers files into a single entry for each. I use the filters section to exclude particular files which would cause and Security exception to be thrown. The files are from javax.mail package.

It produces three jar files once built:
  • original-ProjectName.jar - The package application without dependencies.
  • ProjectName-shade.jar - The none shaded application with dependencies.
  • ProjectName.jar - The shaded application with dependencies. (i.e. a renamed package)