The Holy Java

Building the right thing, building it right, fast

Posts Tagged ‘AOP’

Most interesting links of February ’12

Posted by Jakub Holý on February 29, 2012

Recommended Readings

  • List of open source projects at Twitter including e.g. their scala_school – Lessons in the Fundamentals of Scala and effectivescala – Twitter’s Effective Scala Guide
  • M. Fowler & P. Sadalage: Introduction into NoSQL and Polyglot Persistence (pdf, 11 slides) – what RDBMS offer and why it sometimes isn’t enough, what the different NoSQL incarnations offer, how and on which projects to mix and match them
  • Two phase release planning – the best way to plan something somehow reliably is to just start doing it, i.e. just start the project with the objective of answering “Can this team produce a respectable implementation of that system by that date?” in as short time as possible (i.e. few weeks). Then: “Phase 2: At this point, there’s a commitment: a respectable product will be released on a particular date. Now those paying for the product have to accept a brute fact: they will not know, until close to that date, just what that product will look like (its feature list). What they do know is that it will be the best product this development team can produce by that date.” Final words: “My success selling this approach has been mixed. People really like the feeling of certainty, even if it’s based on nothing more than a grand collective pretending.”
  • Tumblr Architecture – 15 Billion Page Views A Month And Harder To Scale Than Twitter – what SW (Scala, Finagle, heavily partitioned MySQL, …) and HW they use, the architecture (Firehose – event bus, cell design), lessons learned (incl. “MySQL (plus sharding) scales, apps don’t.”
  • Jay Fields’ Thoughts: Compatible Opinions on Software – about teams and opinion conflicts – there are some areas where no opinion is really right (e.g. powerful language vs. powerful IDE) yet people may have very strong feeling about them. Be aware of what your opinions are and how strong they are – and compose teams so that they include more less people with compatible (not same!) opinions – because if you team people with strong opposing opinions, they’ll loose lot of productivity. Quotes: “I also believe that you can have two technically excellent people who have vastly different opinions on the most effective way to deliver software.” “I suggest that you do your best to avoid working with someone who has both an opposing view and is as inflexible as you are on the subject. The more central the subject is to the project, the more likely it is that productivity will be lost.”
  • Jay Fields’ Thoughts: Lessons Learned while Introducing a New Programming Language (namely Clojure) – introducing a new language and winning the hearts of (sufficient subset of) the people is difficult and requires lot of extra effort. This is both an experience report and a pretty good guide for doing it.
  • Jay Fields’ Thoughts: Life After Pair Programming – a proponent of pair-programming comes to the conclusion that in some contexts pairing may not be beneficial, i.e. the benefits of pair-programming don’t overweight the costs (for a small team, small software, …)
  • The Why Monitoring Sucks (and what we’re doing about it) – the #monitoringsucks initiative- what tools there are, why they suck, what to do, new tools, what metrics to collect, blogs, …
  • JBoss Byteman 2.0.0: Bytecode Manipulation, Testing, Fault Injection, Logging – a Java agent which helps testing, tracing, and monitoring code, code is injected based on simple scripts (rules) in the event-condition-action form (the conditions may use counters, timers etc.). Contrary to AOP, there is no need to create classes or compile code. “Byteman is also simpler to use and easier to change, especially for testing and ad hoc logging purposes.” “Byteman was invented primarily to support automation of tests for multi-threaded and multi-JVM Java applications using a technique called fault injection.” It was used e.g. to orchestrate the timing of activities performed by independent threads, for monitoring and statistics gathering, for application testing via fault injection. Contains a JUnit4 Runner for easily instrumenting the code under test, it can automatically load a rule before a test and unload it afterwards:
    @Test
    @BMRule(name="throw IOException at 1st call",
    targetClass = "TextLineProcessor",
    targetMethod = "processPipeline",
    action = "throw new java.io.IOException()")
    public void testErrorInPipeline() throws Exception { ... }
  • How should code search work? – a thought-provoking article about how much better code completion could be if it profited more from patterns of usage in existing source codes – and how to achieve that. Intermediate results available in the Code Recommenders Eclipse plugin.

REST

  • What Makes Jersey Interesting: Parameter Classes (by Coda Hale, 5/2009) – brief yet rich and very practical introduction into Jersey (the reference implementation of JAX-RS. i.e. REST, for Java) including error handling, parameter classes (automatic wrapping of primitive values). The following article, What Makes Jersey Interesting: Injection Providers, might be of interest too.
  • How to GET a Cup of Coffee, 10/2008 – good introduction into creating applications based on REST, explained on an example of building REST workflow for the ordering process in Starbucks – a “self-describing state machine”. The advantage of this article is that it presents the whole REST workflow with GET, OPTIONS, POST, PUT and “advanced” features such as the use of If-Unmodified-Since/If-Match, Precondition Failed, Conflict. The workflow steps are connected via the Location header and a custom <next> link tag with rel and uri. Other keywords: etag, microformats, HATEOS (-> derive the next resource to access from the links in the previous one), Atom and AtomPub, caching (web trades latency for scaleability; if 1+s latency isn’t acceptable than web isn’t the right platform), URI templates (-> more coupling than links in responses), evolution (-> links from responses, new transitions), idempotency. “The Web is a robust framework for integrating systems at local, enterprise, and Internet scale.”

Links to Keep

Tools, Libraries etc.

  • ClusterSSH – whatever commands you execute in the master SSH session are also execute in the slave sessions – useful if you often need to execute the same thing on multiple machines (requires Perl); to install on Mac: “brew install csshx”
  • HTML5 Boilerplate (H5BP) – customizable initial HTML5 project template for a website; can be combined e.g. with Bootstrap, the HTML/JS/CSS toolkit (there is even a script to set them both up). Includes server configs for optimal performance, “delivers best practices, standard elements”.
  • High performance libraries in Java – disruptor, Java Chronicle (ultra-fast in-memory db), Colt Matrix library (scientific computations), Javolution (RT Java), Trove collections for primitives, MG4J (free full-text search engine for large document collections), some serialization & other banchmarks links.
  • Twitter Finagle – “library to implement asynchronous Remote Procedure Call (RPC) clients and servers. Finagle is flexible enough to support a variety of RPC styles, including request-response, streaming, and pipelining; for example, HTTP pipelining and Redis pipelining. It also makes it easy to work with stateful RPC styles; for example, RPCs that require authentication and those that support transactions.” Supports also failover/retry, service discovery, multiple protocol (e.g. http, thrift). Build on Netty, Java NIO. See the overview and architecture.
  • Eclipse Code Recommenders – interesting plugin in incubation that tries to bring more more intelligent completion based more on context and the wisdom of the crowds (i.e. patterns of usage in existing source codes) to Eclipse

Clojure Corner

  • Clojure/huh? – Clojure’s Governance and How It Got That Way – an interesting description how the development of Clojure and inclusion of new libraries is managed. “Rich is extremely conservative about adding features to the language, and he has impressed this view on Clojure/core for the purpose of screening tickets.” E.g. it took two years to get support for named arguments – but the result is a much better and cleaner way of doing it.
  • Clojure Monads Series – comprehensive explanations of monads starting with Monads In Clojure

Quotes

A language that doesn’t affect the way you think about programming, is not worth knowing-

 - Alan Perlis

Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot.

Eric S. Raymond, “How to Become a Hacker”

Posted in General, j2ee, Languages, Testing, Tools, Top links of month | Tagged: , , , , , , , , , , , | Comments Off

Cool Tools: Fault Injection into Unit Tests with JBoss Byteman – Easier Testing of Error Handling

Posted by Jakub Holý on February 25, 2012

How do you test error handling in your application? Do you? Is it at all possible to simulate SocketTimeoutException, SQLException? Normally the answer would be that it isn’t possible or very difficult, requiring a complicated setup. Not anymore – with JBoss Byteman you can easily inject whatever code – e.g. throw new SocketTimeoutException() – in any place – e.g. Socket.connect. The code is injected before your test runs and unloaded when it finishes. Here is an example:

@RunWith(BMUnitRunner.class)
public class BytemanJUnitTests {
@Test(expected=MyServiceUnavailableException.class)
   @BMRule(name="throw timeout at 1st call",
   targetClass = "Socket",
   targetMethod = "connect",
   action = "throw new java.io.IOException()")
   public void testErrorInPipeline() throws Exception {
      // Invokes internally Socket.connect(..):
      new MyHttpClient("http://example.com/data").read();
   }
}

Read the rest of this entry »

Posted in Testing, Tools | Tagged: , | 10 Comments »

Hacking A Maven Dependency with Javassist to Fix It

Posted by Jakub Holý on October 19, 2011

Have you ever wondered what to do when needing “just a small change” to a third-part library your project depended on? This post describes how to use Maven and Javassist to take a dependency of your project, instrument it to modify its behavior, re-pack it, and release it as an artifact with a different name (so that you me depend on my-customized-lib instead of on lib).

The process is as follows:

  1. Phase process-sources - maven-dependency-plugin unpacks the dependency to classes/
  2. Phase compile (implicit) – compile the bytecode manipulation code
  3. Phase process-classes - exec-maven-plugin executes the compiled Javassist instrumenter to modify the unpacked classes
  4. Phase test – run tests on the instrumented code
  5. Phase package – let maven-jar re-package the instrumented classes, excluding the instrumenter itself

Read the rest of this entry »

Posted in Languages, Tools | Tagged: , , , | 2 Comments »

Practical Introduction into Code Injection with AspectJ, Javassist, and Java Proxy

Posted by Jakub Holý on September 7, 2011

The ability to inject pieces of code into compiled classes and methods, either statically or at runtime, may be of immense help. This applies especially to troubleshooting problems in third-party libraries without source codes or in an environment where it isn’t possible to use a debugger or a profiler. Code injection is also useful for dealing with concerns that cut across the whole application, such as performance monitoring. Using code injection in this way became popular under the name Aspect-Oriented Programming (AOP). Code injection isn’t something used only rarely as you might think, quite the contrary; every programmer will come into a situation where this ability could prevent a lot of pain and frustration.

This post is aimed at giving you the knowledge that you may (or I should rather say “will”) need and at persuading you that learning basics of code injection is really worth the little of your time that it takes. I’ll present three different real-world cases where code injection came to my rescue, solving each one with a different tool, fitting best the constraints at hand.

Read the rest of this entry »

Posted in Languages, Tools | Tagged: , , , , | 9 Comments »

Introduction to ObjectTeams/Java, a Role-Based Approach to Modularity With AOP

Posted by Jakub Holý on March 27, 2011

I’ve recently stumbled upon an interesting Eclipse project called ObjectTeams/Java (OT/J), which promises improved reusability and maintenance and support for evolvable architectures by creating well-encapsulated bundles of behavior – modules – that can be applied to existing classes (via AOP), when they are in the appropriate context of interaction (and not simply always, as is the case with AOP). An example application is the addition of NonNull constraint to JDT via an OT/Equinox plugin, without the necessity to modify JDT’s base classes. I’ve decided to write down my discoveries as the project is missing a clear and brief introduction (though it has otherwise very good documentation). This blog borrows heavily from [1]. Read the rest of this entry »

Posted in Languages, Tools | Tagged: , , , | Comments Off

Implementing build-time bytecode instrumentation with Javassist

Posted by Jakub Holý on June 25, 2010

If you need to modify the code in class files at the (post-)build time without adding any third-party dependencies, for example to inject cross-cutting concerns such as logging, and you don’t wan’t to deal with the low-level byte code details, Javassist is the right tool for you. I’ve already blogged about “Injecting better logging into a binary .class using Javassist” and today I shall elaborate on the instrumentation capabilities of Javassist and its integration into the build process using a custom Ant task.

Read the rest of this entry »

Posted in Languages | Tagged: , , , | 3 Comments »

Enforcing a common log format with AspectJ

Posted by Jakub Holý on April 8, 2010

Enforcing a common log format with AspectJ

Andy Wilson has recently blogged about the need for uniformly formatted log messages containing all the necessary information to make log parsing easier and mentioned an extensive refactoring he did on a project to achieve this. One of the readers mentioned that he could save the effort of manually modifying the log statements and use AOP to add the formatting automatically. Well, here is the solution.

Before we dive into the code, I should mention that I do not include a user name in the log, because it is not clear how to obtain it. If it was e.g. stored in a ThreadLocal variable, it would be easy to access it and include it in the log statement. Another thing is that if we could limit ourselves to Log4j instead of commons-logging, we could achieve the same with less effort using a custom formatter and perhaps Log4j’s Nested Diagnostic Context.

The code is basically quite simple – we have one AspectJ aspect using the annotation-style, which intercepts calls to commons-logging’s info(Object) and info(Object, Throwable) and re-formatts the message before handing it over to the actual logger.

package net.jakubholy.example.aoplog.aspect;

import org.apache.commons.logging.*;
import org.aspectj.lang.*;
import org.aspectj.lang.annotation.*;

@Aspect
public class LogFormattingAspect {

    private static final Log LOG = LogFactory.getLog(LogFormattingAspect.class);

    @Around("call(public void org.apache.commons.logging.Log.info(Object)) && args(msg) && !within(LogFormattingAspect)")
    public Object formatMessageLog(
            final Object msg
            , final ProceedingJoinPoint invocation
            , final JoinPoint.EnclosingStaticPart callerContext) throws Throwable {
        return formatLogAndProceed(msg, null, invocation, callerContext);
    }

    @Around("call(public void org.apache.commons.logging.Log.info(Object, Throwable)) && args(msg, exception) && !within(LogFormattingAspect)")
    public Object formatMessageLog(
            final Object msg
            , final Throwable exception
            , final ProceedingJoinPoint invocation
            , final JoinPoint.EnclosingStaticPart callerContext) throws Throwable {
        return formatLogAndProceed(msg, exception, invocation, callerContext);
    }

    private Object formatLogAndProceed(final Object msg, final Throwable exception
            , final ProceedingJoinPoint invocation
            , final JoinPoint.EnclosingStaticPart callerContext
            ) throws Throwable {

        final String callingMethod = callerContext.getSignature().getName();

        LOG.info("Log.info has been called from the method " + callingMethod +
                " with message=" + msg + ", exception=" + exception);

        final Object[] arguments = invocation.getArgs();
        arguments[0] = formatMessage(callingMethod, msg);

        return invocation.proceed(arguments);
    }

    private String formatMessage(final String callingMethod,
            final Object originalMessage) {
        return "APPMSG: " + callingMethod + ": " + originalMessage;
    }
}

If you are new to AspectJ then you need to understand that

  • the methods annotated with @Around are invoked whenever Log.info(..) is called
  • AspectJ provides values for the interceptor method’s arguments including runtime and static information about the intercepted call, as represented by the *JoinPoint* instances
  • those methods extract some information about the actual call and its arguments from the invocation context provided by AspectJ
  • finally, they invoke the original intercepted method by calling proceed()

The part args(msg, exception) may seem tricky – it binds the intercepted method arguments to those of the intercepting method (i.e. final Object msg, final Throwable exception). This isn’t necessary since we may access them via invocation.getArgs() as we anyway do but it’s more convenient.

To apply the aspect to you code you need to weave them into it. You can choose either Load-Time Weaving (LTW), which uses Java 5′s -javaagent option and instruments classes as they’re loaded by the JVM based on configuration in an aop.xml file and which provides rather nice debugging output (when enabled), or Bytecode Weaving (also called build- or compile-time weaving), which injects the aspects into .class files using the command-line compiler/weaver ajc or AspectJ’s Ant tasks. During development I prefer LTW, which is more flexible, but for use in a production environment it’s better to weave the bytecode because LTW consumes more memory (due to custom classloaders) and CPU.

Try it out

The easiest way to try this out is to use Maven 2:

  1. Download the source code archive aop-log-formatter-0.0.1-sources.jar
  2. Unpack them somewhere
  3. In the directory with the sources (namely pom.xml), execute
    mvn -Pexecute-from-sources compile exec:exec
  4. This will download some maven/project dependencies (a lot, if you don’t use maven often, sorry), compile the sources and execute the application while printing its log to the console

If you do not want to use maven:

  1. Download the source code archive aop-log-formatter-0.0.1-sources.jar
  2. Download also the compiled binaries aop-log-formatter-0.0.1.jar
  3. Download the dependencies, as recorded in the project’s pom.xml (commons-logging, AspectJ weaver)
  4. Execute it with Load-Time Weaving (java 5 or higher required; it’s assumed that all dependencies are in the same folder):
    java -cp aop-log-formatter-0.0.1.jar:commons-logging-1.1.1.jar -javaagent:aspectjweaver-1.6.8.jar net.jakubholy.example.aoplog.ExampleLoggingClass

The output will be long, because the aop.xml included in the jar enables the most detailed AspetJ logging but in the end you should see something like:

[INFO] [INFO] LogFormattingAspect - Log.info has been called from the method main with message=A message w/o an exception., exception=null
[INFO] [INFO] ExampleLoggingClass - APPMSG: main: A message w/o an exception.
[INFO] [INFO] LogFormattingAspect - Log.info has been called from the method main with message=Another message accompanied by an exception., exception=java.lang.RuntimeException: I'm the exception!
[INFO] [INFO] ExampleLoggingClass - APPMSG: main: Another message accompanied by an exception. java.lang.RuntimeException: I'm the exception!

You can see that the ExampleLoggingClass log message has been decorated with the prefix APPMSG and the method name (main).

Posted in Languages | Tagged: , , | Comments Off

Compiling with AspectJ’s ajc compiler from Maven

Posted by Jakub Holý on December 10, 2009

I needed to compile AspectJ classes (.java with annotations) with ajc and I wanted to have that integrated into the Maven build process. I tried several means, finally finding the one that worked.

Note: I had to use ajc even though I was using the pure java 5 syntax based on annotations instead of the legacy AspectJ syntax due to bug in AspectJ (fixed in v. 1.6.6).

Failed Attempts

aspectj-maven-plugin v1.2

First I tried the AspectJ Maven plugin but it didn’t work for me because I had a special need – a project containing only an aspect while the plugin requires, if I remember correctly, also the advised sources to be in the project. A fix is available and should be included in the version 1.3 but the project doesn’t seem to be very active so who knows when it will be released. See MASPECTJ-7.

maven-compiler-plugin for aspectj

Next I tried the maven-compiler-plugin, which supports various back-ends including AspectJ with the dependency on plexus-compiler-aspectj and compilerId set to aspectj. Unfortunately the plexus-compiler-aspectj is quite out of date, supporting only AspectJ 1.3 while I needed 1.6.

Finally the Success: maven-antrun-plugin

Being failed by Maven plugins, I had to resort to the standard way of running ajc via Ant. Fortunately Maven has a very good integration of Ant and its tasks.

The only problem here was that Ant requires ${java.home} to point to JDK (and not JRE) to find javac. It doesn’t help to set the envrionmental variable JAVA_HOME to point to the JDK because Maven resets it to $JAVA_HOME/jre in the case – see MANTRUN-91. The solution is to add tools.jar (which includes javac classes) to maven-antrun-plugin’s dependencies.

The corresponding piece of pom.xml:

<build>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <!-- Tell javac not to compile sources for antrun will do it -->
    <configuration>
        <excludes>
            <exclude>**/*.*</exclude>
        </excludes>
    </configuration>
  </plugin>

  <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.3</version>
    <dependencies>
      <dependency>
        <groupId>sun.jdk</groupId>
        <artifactId>tools</artifactId>
        <version>1.5.0</version>
        <scope>system</scope>
        <systemPath>${java.home}/../lib/tools.jar</systemPath>
      </dependency>
      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjtools</artifactId> <!-- apectj ant plugin -->
        <version>1.6.0</version>
      </dependency>
    </dependencies>

    <executions>
      <execution>
        <phase>compile</phase>
        <goals>
          <goal>run</goal>
        </goals>
        <configuration>
          <tasks>
            <echo>AntRun: Compiling AspectJ classes with ajc, java.home=${java.home}</echo>
            <taskdef
              resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"
              classpathref="maven.plugin.classpath" />

            <iajc
              srcDir="src/main/java"
              destDir="target/classes"
              verbose="true"
              showWeaveInfo="true"
              source="1.5"
              classpathRef="maven.compile.classpath"
              Xlint="ignore" >

              <exclude name="eu/ibacz/pbns/util/aspect/ExampleTimingAnnotatedAspect.java"/>
            </iajc>

          </tasks>
        </configuration>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

Note: maven-antrun-plugin v1.3 uses Ant 1.7.1 – see http://maven.apache.org/plugins/maven-antrun-plugin/dependencies.html

Conclusion

It’s a bit tricky but very well possible to run AspectJ compiler instead of javac during a maven build. The most flexible way is to use the AspectJ Ant task and maven-antrun-plugin though in more standard cases the aspectj-maven-plugin can serve you well too.

Posted in Languages | Tagged: , , , | 1 Comment »

PatternTesting: Automatically verifying the good application of architectural/design patterns in code

Posted by Jakub Holý on September 25, 2009

PatternTesting is a mature open-source project that enables you to automatically check at the compile- or run-time that architectural/design/implementation decisions are implemented and bad practices avoided in the code. The main differences from tools like FindBugs and PMD are that you can implement tests spanning multiple files (classes) and that aside of compile-time checks there are also run-time checks (using AOP with ApsectJ) to do things like “ensuring that there are no more than 10 calls to the database per user case” and providing better error messages in the case of e.g. IOException.

Read more in a The Server Side’s introductory article and on the project’s page.

I haven’t yet the chance to try this out but it really intrigues me.

Posted in Languages, Testing | Tagged: , , , , | Comments Off

Injecting timing aspect into JUnit test in Eclipse using AspectJ, AJDT

Posted by Jakub Holý on July 10, 2009

Introduction

This blog describes my experience with using AOP, namely AspectJ, to measure the individual execution times and their average of a particular low-level method invoked many times during a JUnit test run from within Eclipse. It concentrates on creating the aspect and integrating (weaving) it into the JUnit test execution in the Eclipse environment.

Of course it would be easier to use e.g. profiler but I wanted to play with AOP/AspectJ to learn it better because it’s an incredibly useful tool for a number of problems and you can use it even if you don’t have access to the application’s source code and/or cannot control the runtime environment (such as running it in a profiler).

Why AspectJ?

There are also other AOP tools for Java but it seems that AspectJ is the most wide-spread one, especially since its merge with AspectWerkz. I used to dislike it because it required a special extended Java syntax and compiler but this isn’t true anymnore (more on that later).

Disclaimer

I’m only learning AspectJ, so the solution may be not and likely isn’t the best one. I appreciate improvement suggestions.

Preparing the environment

I use Pulse to set up my Eclipse environment. For this I’ll use:

  • Eclipse 3.4 for Java EE (Pulse doesn’t yet support 3.5)
  • AJDT 2.0.0
  • AspectJ 1.6.5
  • JUnit 4
  • JDK 1.5.0.18 (the test fails with 1.6 due to xml libs incompatibility) and Java 5.0 syntax

Implementing the timing aspect

My goal is to create an aspect invoked around the method in question that will measure the time it takes for the method to execute, log it, and compute and log the average execution time.

Since AspectJ 5 we have two options – either using the older custom AspectJ syntax with AspectJ compiler or using annotations. I’ll explore both possibilities.

Project structure

First, we have a Java project with the junit test that we want to run with the timing aspect. It depends on another project with the actual class and method whose performance we want to measure.

MyLibraryProject

  • /src/main/java/com/tonbeller/jpivot/xmla/XMLA_SOAP.java

MyTestProject

  • /src/main/java/
    • eu/ibacz/studna/jpivot/OLAPModelStructure.java
      - calls (indirectly) XMLA_SOAP.discoverMem during its execution
  • /src/test/java/
    • eu/ibacz/studna/jpivot/OLAPModelStructurePerformanceTest.java
      - standard JUnit4 test case

We create another project to hold our new shiny aspect: File > New > Other… > AspectJ > AspectJ Project =>

MyAspectProject

  • /src/
    • eu/ibacz/pbns/util/aspect/TimingAspect.aj (solution 1)
    • eu/ibacz/pbns/util/aspect/TimingAnnotatedAspect.java (solution 2)

Solution 1: using custom ApectJ syntax

Before AspectJ 5 this was the only option and it is still more powerful and has better support of AJDT (according to the FAQ). Basically you write the aspect in an extended Java syntax in an .aj file and compile it with a special AspectJ compiler – though this is done behind the scene for you thanks to having created an AspectJ project, which also provides you with a special AspectJ/Java editor for .aj and .java aspect files.

Enough talking, let’s see the aspect:

File eu/ibacz/pbns/util/aspect/TimingAspect.aj:

package eu.ibacz.pbns.util.aspect;

import ...

public aspect TimingAspect {

    // instance/class field ...

    public TimingAspect() {
        formatter = NumberFormat.getIntegerInstance();
        formatter.setMinimumIntegerDigits(3);
        System.out.println(getClass() + " instantiated!");
    }

//  before(): execution(public * com.tonbeller.jpivot..XMLA_SOAP.*(..) ) {
//      System.err.println("About to call " + thisJoinPoint.getSignature().toShortString() + ", args:" + Arrays.toString(thisJoinPoint.getArgs()) );
//  }

    Object around() : execution( * com.tonbeller.jpivot..XMLA_SOAP.discoverMem(..) ) {

        final long startTimeCpuMs = getCurrentTimeMs();
        final long startTimeMs = System.currentTimeMillis();

        Object result = proceed();

        final long endTimeMs = System.currentTimeMillis();
        final long endTimeCpuMs = getCurrentTimeMs();

        final long execTimeMs = endTimeMs - startTimeMs;
        final long execTimeCpuMs = endTimeCpuMs - startTimeCpuMs;

        ++totalExecutionCount;
        totalExecutionTimeMs += execTimeMs;
        totalCpuExecutionTimeMs += execTimeCpuMs;

        final String msg = "executing discoverMem #" + formatter.format(totalExecutionCount) +
                " took " + execTimeCpuMs + "ms of CPU, " +
                execTimeMs + "ms real; current average is [ms/call]: " +
                totalCpuExecutionTimeMs / totalExecutionCount + " for CPU, " +
                totalExecutionTimeMs / totalExecutionCount + " real time.";
        System.out.println(getClass().getName() + ": " + msg);

        return result;
    }

}

(I’ve ommited the fields and some methods for brevity.)

PS: You can use the commented-out before adivce to print all methods called on XMLA_SOAP including their name and arguments. This is useful to find out whether the method you’re trying to measure is actually called at all.

Solution 2: using annotation (@AspectJ)

Since AspectJ 5 we can use a normal Java class with special annotations to define an aspect. It’s less powerful (see above) but more familiar to a Java developer and more comfortable to use since it doesn’t need any special compiler (the annotations are processed by AspectJ during weaving).

File eu/ibacz/pbns/util/aspect/TimingAnnotatedAspect.java:

package eu.ibacz.pbns.util.aspect;

import ...

public class TimingAnnotatedAspect {

    // instance/class field ...

    public TimingAspect() {
        formatter = NumberFormat.getIntegerInstance();
        formatter.setMinimumIntegerDigits(3);
        System.out.println(getClass() + " instantiated!");
    }

    @Around("execution( * com.tonbeller.jpivot..XMLA_SOAP.discoverMem(..) )")
    public Object around(ProceedingJointPoint pjp) {

        final long startTimeCpuMs = getCurrentTimeMs();
        final long startTimeMs = System.currentTimeMillis();

        Object result = pjp.proceed();

        final long endTimeMs = System.currentTimeMillis();
        final long endTimeCpuMs = getCurrentTimeMs();

        final long execTimeMs = endTimeMs - startTimeMs;
        final long execTimeCpuMs = endTimeCpuMs - startTimeCpuMs;

        ++totalExecutionCount;
        totalExecutionTimeMs += execTimeMs;
        totalCpuExecutionTimeMs += execTimeCpuMs;

        final String msg = "executing discoverMem #" + formatter.format(totalExecutionCount) +
                " took " + execTimeCpuMs + "ms of CPU, " +
                execTimeMs + "ms real; current average is [ms/call]: " +
                totalCpuExecutionTimeMs / totalExecutionCount + " for CPU, " +
                totalExecutionTimeMs / totalExecutionCount + " real time.";
        System.out.println(getClass().getName() + ": " + msg);

        return result;
    }

}

As you can see, we’ve replaced the special AspectJ syntactical elements with annotationes @Aspect and @Around (there is also @Pointcut and others).

(I’ve ommited the fields and some methods for brevity.)

Conclusion: Annotations vs. custom syntax

When deciding
whether to use the the old custom AspectJ syntax and .aj files with an
AspectJ compiler or the new annotation-based aspects in standard .java
files you have to take into account that the annotation-based aspects
are less powerful (regarding what all can be weaved) and have weaker
support of the AJDT tooling so that your aspects may not display in its
views etc.

Common project info

For both projects we need to have the class to modify with the aspect, in our case XMLA_SOAP, on the classpath, to get some special support from AJDT (see below).

The good thing when using AJDT is that if a pointcut definition (such as the execution(…) above) doesn’t match an existing class/method, you will be warned about it – in Eclipse there will be the standard warning marker with text like “no match for this type name: XMLA_SOAP [Xlint:invalidAbsoluteTypeName]“. This works both for .aj and .java files though it may not discover all issues.

The common code, if you’re interested:

    private ThreadMXBean threadMxb;

    /**
     * Return the current time in miliseconds, if possible, return only the current thread's CPU time, if not,
     * return system time.
     * <p>
     * thread's CPU time is usually few times less than the absolute time between
     * its start and end due to the fact that it has to share the CPU with other processes/threads.
     */
    private long getCurrentTimeMs() {
        return getThreadMxBean().isCurrentThreadCpuTimeSupported()?
                threadMxb.getCurrentThreadCpuTime() / 1000000 : System.currentTimeMillis();

    }

    /** Lazy-init getter. */
    private ThreadMXBean getThreadMxBean() {
        if (threadMxb == null) {
            threadMxb = ManagementFactory.getThreadMXBean();

            if (threadMxb.isThreadCpuTimeSupported()) {
                LOG.info("Thread user/cpu time monitoring supported.");
                if (threadMxb.isThreadCpuTimeSupported() &amp;&amp; threadMxb.isThreadCpuTimeEnabled()) {
                        LOG.info("Thread user/cpu time monitoring supported&amp;enabled."); // TODO do only once
                } else {
                    LOG.warn("Thread user/cpu time monitoring supported but disabled.");
                }
            } else {
                LOG.warn("Thread user/cpu time monitoring NOT supported.");
            } // supported thr. time
        }

        return threadMxb;
    } /* getThreadMxBean */

Integrating the aspect into the JUnit test

Our tracing aspect is ready and we want to apply it to XMLA_SOAP.discoverMem when running our JUnit test OLAPModelStructurePerformanceTest. Unfortunately AJDT doesn’t provide any support for running JUnit tests with AspectJ support though it does that for normal java programs via the additional Run As… > AspectJ/Java Application menu item therefore we will need to do it manually. Maybe there is a better way but this is what I did:

  1. Get aspectjweaver.jar – it includes complete AspectJ runtime plus Java 5 agent lib.
  2. Modify the Run configuration of the JUnit test (Run > Run Configurations) as follows:
    1. On the tab Arguments, add the VM argument
      -javaagent:/path/to/aspectjweaver.jar
    2. On the tab Classpath, click on User Entries and add there the project MyAspectProject so that it can see the aspect.
  3. In the project MyTestProject create under /src/test/java/ (or any other source folder) META-INF/aop.xml with the content shown below.

File aop.xml :

<aspectj>
    <aspects>
        <!-- aspect name="eu.ibacz.pbns.util.aspect.TimingAspect"/--> <!--  fails if not found -->
        <aspect name="eu.ibacz.pbns.util.aspect.TimingAnnotatedAspect"/>
    </aspects>
</aspectj>

This file tells AspectJ’s Load-Time Weaver what aspects to introduce into the existing classes. Without it no instrumentation would occur. You can configure here which of the 2 aspects to use. You can also “specify
the set of types that should be woven. If no include elements are specified
then all types visible to the weaver will be woven”. See the documentation on aop.xml and Load-Time Weaving configuration for more info.

Troubleshooting load-time weaving

If you need to learn more about what AspectJ does during the weaving and whether it does modify the target class or not (e.g. due to wrong pointcut match pattern or classpath order) you may enable some logging using either some properties on the command-line or by specifying this in the aop.xml:

<aspectj>
    <aspects>
        <!-- aspect name="eu.ibacz.pbns.util.aspect.TimingAspect"/--> <!--  fails if not found -->
        <aspect name="eu.ibacz.pbns.util.aspect.TimingAnnotatedAspect"/>
    </aspects>
    <weaver options="-verbose -showWeaveInfo "> <!-- add -debug to print every class [not] woven  -->
        <include within="com.tonbeller.jpivot.xmla..*"/> <!-- Notice the 2 dots to include also subpackages -->
        <include within="eu.ibacz..*"/>
    </weaver>
</aspectj>

If the weaving proceeds as expected, this should produce an output similar to the one below:

[AppClassLoader@1858610] info AspectJ Weaver Version DEVELOPMENT built on Friday Aug 29, 2008 at 00:25:33 GMT
[AppClassLoader@1858610] info register classloader sun.misc.Launcher$AppClassLoader@1858610
[AppClassLoader@1858610] info using configuration /home/jholy/devel/MyTestProject/target/classes/META-INF/aop.xml
[AppClassLoader@1858610] info register aspect eu.ibacz.pbns.util.aspect.TimingAspect
[AppClassLoader@1858610] info processing reweavable type com.tonbeller.jpivot.xmla.XMLA_Model: com/tonbeller/jpivot/xmla/XMLA_Model.java
[AppClassLoader@1858610] info successfully verified type eu.ibacz.pbns.util.aspect.TimingAspect exists.
  Originates from eu/ibacz/pbns/util/aspect//home/jholy/devel/MyAspectProject/src/eu/ibacz/pbns/util/aspect/TimingAspect.aj
[AppClassLoader@1858610] weaveinfo Join point 'method-execution(void com.tonbeller.jpivot.xmla.XMLA_Model.retrieveMemberChildren(com.tonbeller.jpivot.xmla.XMLA_Member))'
 in Type 'com.tonbeller.jpivot.xmla.XMLA_Model' (XMLA_Model.java:1094) advised by around advice from 'eu.ibacz.pbns.util.aspect.TimingAspect' (TimingAspect.aj:56)

The line ‘info register aspect eu.ibacz.pbns.util.aspect.TimingAspect‘ tells us that AspectJ has found the aspect referenced from aop.xml. If the aspect class didn’t exist then it would print an error message. The information about registered aspects, configuration aop.xml and AspectJ version is displayed thanks to the option -verbose.

The line ‘weaveinfo Join point …‘ tells us that AspectJ has actually found and modified the target and is enabled with the -showWeaveInfo flag.

If you enabled -debug in aop.xml, AspectJ would print the list of classes that it has processed (whether there was an aspect to apply or not) – this can help you to verify that it doesn’t ignore your target class.

Note: all weaver messages are prefixed with the classloader the weaver instance is attached to, e.g. in a web server you’d have multiple instances.

Conclusion

It works! :-)

Limitations of aop.xml

AspectJ is extremely powerful, especially because it isn’t limited to “advicing” or intercepting method calls but can also intercept field access, add fields, inject interface implementation into classes and much more.

What I find quite limiting is that in aop.xml you cannot specify very much what should or should not be woven, only the classes to include in/exclude from the process. If you want to limit to what methods etc. your apect applies, you have to change that in its source code and recompile it :-)

Resources and links

Other

Posted in Languages | Tagged: , , , , , | 2 Comments »