Is AspectJ Still Useful for Android? Part 2

In the first part of this post, I showed some ways that AspectJ would be useful in android development when it comes to testing. This final part demonstrates one way of incorporating AspectJ, and how I manage to make the aspect weaving somewhat configurable in the build process.

Android + AspectJ

A search on the internet will show that there are various ways of integrating AspectJ into the Android build process, including doing it manually or using a gradle plugin. I have been using the android-gradle-aspectj plugin for the last few years, since it has some useful features and the author seems to keep it maintained fairly well.

A basic setup for this plugin requires adding it to the buildscript repositories and dependencies blocks. I have this in build.gradle in the project root directory.

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:x.x.x'
    classpath 'com.archinamon:android-gradle-aspectj:x.x.x'
  }
}

Then apply the plugin where required, so in the module build.gradle:

apply plugin: 'com.archinamon.aspectj'

or

plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj'
}

This should be enough to run a simple case, such as the example from the first post. Please see the plugin documentation for more advanced configurations.

To verify that the aspect has been compiled and weaved during the build process, you can check:

  • the aspectj directory in the module build directory, containing the compiled aspect class files
  • some log files generated by the plugin in the module build directory, ajc-transform.log and ajc-compile.log
  • the build output log for the AspectJ plugin tasks, compile[Build variant]Aspectj and transformClassesWithAspectjFor[Build variant].

Determining When to Use Aspects or Not

If we’re only using aspects for testing, most of the time we don’t want the aspect code to be incorporated into the build process. An easy way to determine when to weave the aspect code or not is to use a Boolean condition.
For instance, in the aspect file include a Boolean condition in the pointcut to determine whether the advice will apply or not:

pointcut myPointcut(): if (aspectjEnabled) && ... // the rest of the pointcut

Here the Boolean value ‘aspectjEnabled‘ is used as a flag that will determine whether the aspect code will apply the advice.

One way of passing this flag to the aspect class is to use the generated BuildConfig class, which can be set in the build file (build.gradle) of the app.

android {
  buildTypes {
    debug {
      // Flags for Aspect testing
      buildConfigField 'boolean', 'aspectjEnabled', true
    }
  }
}

Then in the pointcut of the aspect file, include the flag as a conditional.

pointcut myPointcut(): if (BuildConfig.aspectjEnabled) && ... // the rest of the pointcut

Of course we can go further and set that flag from a gradle project property, rather than hardcoding it in build.gradle.

Now when the build is done, pass a project property to determine whether we want the aspect flag to be set or not.

-PaspectjEnabledProperty=true

I also have this extra bit to set the aspect flag to false if the project property was not specified (which is the default when we want to do a normal build without aspects).

ext.aspectjEnabledProperty = getAspectJEnabledFlag()

def getAspectJEnabledFlag() {
  if (project.hasProperty('aspectjEnabledProperty'))
    return project.property('aspectjEnabledProperty')
  else
    return false
}

Then in the build file for the app, the value of the aspect flag to be put into the BuildConfig class will be set dynamically.

android {
  buildTypes {
    debug {
      // Flags for Aspect testing
      buildConfigField 'boolean', 'aspectjEnabled', "${aspectjEnabledProperty}"
    }
  }
}

In sumary, this means that if the property ‘aspectjEnabledProperty’ is not passed to the build or is set to false, then the AspectJ weaving does not happen. Then when required, the property can be set for testing that particular bit of code.

Of course you are not restricted to one aspect flag, you can set as many flags as you like for the different tests you want to run.

-PexceptionTestProperty=true -PcrashTestProperty=false -PservicesTestProperty=true

Testing Multiple Types of Errors

In the configuration above, I’ve used a boolean value as the flag to enable/disable aspect weaving in the pointcut. Using a boolean flag is the simplest case, and probably the most common type that used.

However what about if you want to test multiple types of errors and error handling. For instance, if you want to test having the adviced method throw different types of exceptions. Another example is if you want to simulate different status codes as the response from a network call.

Then instead of using a boolean value as the flag, use an integer (or any other simple type) for example.

-PaspectjTestingProperty=1

Then in the build file:

ext.aspectTestingFlag = getAspectTestingFlag()

def getAspectTestingFlag() {
  if (project.hasProperty('aspectjTestingProperty'))
    return project.property('aspectjTestingProperty')
  else
    // default value if property not specified
    return 0
}

android {
  buildTypes {
    debug {
      // Flags for Aspect testing
      buildConfigField 'int', 'aspectTestingFlag', "${aspectjTestingProperty}"
    }
  }
}

Then in the aspect, you can use the integer flag both as a conditional in the pointcut and as an indicator run different code in the advice.

aspect TestAspect {

  pointcut myPointcut(): if (BuildConfig.aspectjTestingFlag != 0) && ... // the rest of the pointcut

  int around(): myPointcut() {
    switch (BuildConfig.aspectjTestingFlag) {
      case 1:
      // return a particular status code, or throw a particular exception type

      case 2:
      // return a different status code, or throw a different exception type

      case 3:
      // return yet another status code, or throw a third different exception type

      default:
      return proceed();
    }
  }
}

Caveats

Just a few things to be aware of:

  1. As already mentioned, since we can only have AspectJ compile time weaving for Android development, this means some additional build time for the AspectJ tasks.
  2. Unfortunately Android Studio doesn’t have IDE support for AspectJ, since it is based on the community edition of IntelliJ IDEA.
    While the Ultimate version of Intellij does support AspectJ, I prefer using Android Studio.

    Tip:
    Sometimes to get the pointcuts correct I will copy files with the aspect, the classes I want to advice and their lib dependencies into a dummy Eclipse project so that I can use the AspectJ Development Tools (AJDT) to fine tune the pointcut. This allows me to see if the pointcuts are being applied correctly to the joinpoints I want.

  3. Using a Gradle plugin to handle incorporating AspectJ into the build process does make things easier. However this sometimes means having to wait for the authors of the plugin to keep up to date with the latest versions of the android gradle plugin or gradle.

Is AspectJ Still Useful for Android? Part 1

For Java projects I sometimes use AspectJ for various tasks, but for Android projects I initially decided against using it.

There were various reasons for that:

  • The structure of an Android project, and its build process, was already a lot more complicated and slower than for generic Java projects.
  • For Android development, only compile time weaving is supported for AspectJ, which makes it less useful.
  • The Android Studio IDE does not have support for AspectJ.

However I eventually found some uses for aspects when it comes to testing. Another reason I decided to give AspectJ a try was the availability of Android AspectJ plugins for Gradle. They make integrating AspectJ into the Android build process easier, I use this one.

Using aspects I can weave test code into the application code when required for a particular test. Then when no longer needed, I would just do a normal build without the aspect weaving, and the test code is kept totally isolated in the aspect file.
I found this to be a good alternative to what sometimes happens during testing:

  • adding test code for a particular test, and then having to remove it or comment it out afterwards
  • adding temporary logging to find a bug, profile some code, etc

What is it Good For, Some Examples

Testing Crashlytics

without AspectJ:

When testing for Crashlytics, the Firebase documentation recommends adding a temporary button with a click handler that crashes the app.

with AspectJ:

Instead I can weave the crash inducing code into any existing app event I like, e.g a button click, menu click, etc.

Testing exception handling

without AspectJ:

Write some temporary test code to throw an exception to see if the app handles it correctly.

with AspectJ:

Have an aspect that throws the exception from any method I choose. I can also have the pointcut advice multiple methods so that the test exception can be thrown from multiple locations.

Testing interactions with external services

(For instance, checking that Google Play services are available.)

without AspectJ:

Write some test code to simulate the response from the external service that you want to test for. For example, when checking if Google Play services are available then you might want to test that your app correctly handles an unsuccessful result code such as SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, etc.

with AspectJ:

Write an aspect that advices where you call the external service, and have it return the result that you want to test for. It’s up to you whether you want to actually make the call to the external service in the advice using proceed(..) or just have the advice return the result you want.

The Usual Stuff, like Tracing

One of the most common uses of AspectJ is for method tracing, this can be useful for profiling the app or when trying to track down that hard-to-find bug.

without AspectJ:

Add temporary trace logging to the app code that you think might need profiling or be causing a bug.

with AspectJ:

Enable tracing of method calls with logging for any or all method calls that I want by adjusting the pointcut for of a tracing aspect. It’s quick and easy to write a pointcut to advice all methods in a class, for example.

There are plenty of examples of AspectJ tracing aspects around, or you can use android tools to generate trace logs by instrumentation.

An AspectJ Example

Let’s start with a common scenario, a service class with a method that makes a network call (presumably to get some data and apply business logic to it). This service method would be called by an activity or fragment in the app.
Note that this example assumes that you are already familiar with how to program in AspectJ native syntax.

public class BusinessService {

  public Result serviceNetworkCall() {
    return ... // return some data from a network call
  }
}

I want to test that the activity/fragment correctly handles the situation where there is an error when the service method is called. Here is an aspect that can be used to simulate an exception being thrown on the method call.

aspect TestExceptionInjector {

  pointcut injectTestException(): target(BusinessService) && execution(public Result *(..));

  Result around(): injectTestException() {
    // can allow the adviced method to run first before the exception is thrown by calling <em>proceed()</em> first, in case we want some side effects to occur

    // simulate an exception being thrown from the method(s) adviced
    throw new RuntimeException("TEST");
  }
}

In this aspect the pointcut will advice the service method, and throws an exception instead its normal execution. Then we can run the app to check that the Activity / Fragment that calls the service method does handle this error properly.

I can also do this where a reactive library, such as RxJava, is being used in the service class.

public class BusinessServiceRx {

  public Observable<Result> serviceNetworkCallRx() {
    return ... // return some data from a network call
  }

  public Observable<Result> anotherServiceNetworkCallRx() {
    return ... // return some data from a network call
  }
}

privileged aspect TestExceptionInjectorRx {

  pointcut injectTestExceptionRx(): target(BusinessServiceRx) && execution(public Observable<Result> *(..));

  Observable<Result> around(): injectTestExceptionRx() {
    // simulate an exception being thrown downstream from the method(s) adviced
    return Observable.error(new RuntimeException("TEST"));
  }
}

This example also shows that the pointcut in the aspect can advice multiple service methods.

Determining When to Build with Aspects (or Not)

Next, we need to weave the aspect in the example into the app code, and then find some way to determine when to do a build with aspects for testing, and when to just do a normal build. In the concluding part of this post, I will show the workflow I use as one way of doing this.

For Testing Only?

As I have mentioned, when using aspects the test/logging code resides in an aspect file that is isolated from the app code and should never get into a release build. However it is always available when I want to run the tests again, and there is no need to worry about forgetting to remove temporary test code after the testing is done.

The use of AOP (Aspect Oriented Programming) for testing only is purely my personal preference. Of course you can just as easily use AspectJ as part of your development process and include aspects in your app code.

Android Studio 3.0 – Initial Impressions of Tool Support

I have been using Android Studio 3.0 since since the alpha versions, and it is good to see it finally released.

This is just some initial comments on using some common and new Android tools and libraries with the 3.0 version of Android Studio and the associated Android Gradle plugin.

Hopefully this will be useful for anyone thinking of upgrading from Android Studio 2.x.

Java 8 Finally, Maybe

Java 8 was released back in 2014, and with Android Studio 3.0 it is finally supported in Android. Finally I can say goodbye to RetroLambda (although many thanks to the authors for this very useful library).

Just be aware that many of the Java 8 language features will only be available if the minSkdVersion is 24.

Since devices running Nougat or Oreo are still in the minority, supporting older versions will continue to be an issue for a while if you want to use Java 8. Some ideas floated around to support older API version, are to have min API version flavors or  do Build.VERSION checks for the API version in the code to provide alternative code paths.

Desugar

The Jack tool chain has been replaced with the desugar tranformation process to support Java 8. Some older libraries and code may have some problems with this build stage.

JUnit 5

JUnit 5 has also been released recently, and with the help of this plugin you can use it for unit testing in Android Studio.

However if you use JUnit 4 Rules in your tests, there is limited support in JUnit 5 as they are meant to be replaced with extensions. Some Rules may be supported with the JUnit 5 migration support, but if not you will have to wait until the Rules are rewritten as extensions or not use the Rules at all.

Of course this is only for unit testing. Instrumentation tests still depend on JUnit 4 and the AndroidJUnitRunner.

Update (7 Dec 2017)

The authors of the JUnit5 plugin have stated that they now have support for JUnit 5 in instrumentation tests. I won’t be using it for a while since it requires the minSkdVersion to be 26. If anyone has tried this, please let me know how well it works.

Architecture Components, RxJava

I have also been using some of Google’s Architecture Components, but only the ViewModel and LiveData. This is another alternative to design patterns such as MVP or MVVM with Databinding.

If you use RxJava, then this will of course continue to work as it is compatible with Java 6. You may consider replacing RxJava with the more light weight LiveData for activities and fragments, and they can be adapted to each other.

Dependency Injection with Dagger

I have had no problems with Google’s Dagger, but be aware of the API changes for the Android Gradle plugin 3.0 in the gradle build file (e.g. implemention instead of compile, annotationProcessor instead of apt, etc).

See the Android Gradle plugin 3.0 migration guide.

Butterknife, Timber

Some common utilities like Butterknife and Timber for logging are working fine. I’m also using the slf4j binding for Timber without any trouble.

JRebel for Android

During the Android Studio alpha and beta process, JRebel for Android was always playing catch up with the latest version. I still have issues with the current version (2.4.14) of their free edition, so I am using instant run instead at the moment.

I’m a big fan of JRebel so I’m hoping they will have a stable version of their android plugin for Android Studio 3.0 soon.

Update (31 Jan 2018)

JRebel for Android is no longer being actively developed.

AOP with AspectJ

There are various AspectJ plugins for Android,  and the one I have been using in Android Studio 2.x was this one. Unfortunately it doesn’t support the Android plugin for Gradle 3.0 yet, but the author seem to be working on it so hopefully the support will be there soon.

Update (15 Nov 2017)

Version 3.2.0 of the GradleAspectJ-Android plugin now supports the Android plugin for Gradle 3.0. I like this plugin because it supports both aj files and annotation style aspects.

Things will get better

Of course since Android Studio 3.0 has only recently got general release, we should expect tool and library support to improve going forward.

I have only scratched the surface with some common Android tools and libraries, and there are many more around. Please let me know of your experiences with others.

Reusable Aspect Library for Android, Part 2

In part 1 of this post, we created an Android library containing aspects that could be used to intercept code in an application. However the library would require code changes in order to work with other application, and so was not really reusable as it stood.

In this part, we will modify the sample code to make the library more reusable across multiple applications.

Scenario 2 – The Pointcut in the Application

In this example, the aspect tracing code is kept in the aspect library project, but we will put the pointcut in the application.

Create the Projects

Create an Android application project and library project, and configure them as AspectJ projects in Eclipse, same as for part 1. Then add the library project to the application project, both as an Android library and to the application aspectpath.

Code Changes

1. Aspect Library

Once again put the AspectJ tracing code in the library project,  but this time the pointcut has been made abstract.

public abstract aspect BaseTraceAspect {

    /** Pointcut for tracing method flow tracing */
    protected abstract pointcut traceOperations();

    before() : traceOperations() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        log("Entering [" + sig.toShortString() + "]");
    }

    /** Implement in subaspect for actual logging */
    protected abstract void log(String msg);
}

Notice I have also made the log method abstract as well, this leaves it up to the application to determine how it wants to log the tracing output. In general any funcationality that is specific to the application should be made abstract here, and be implemented in the application.

2. Test Application

In the application project, add some code that can be intercepted by the aspect, as for part 1.

Then create another aspect file which subclasses the aspect in the library project. This aspect just implements the pointcut (and in this sample, the logging method as well).

public aspect TraceAspect extends BaseTraceAspect {

    private final static String TAG = "Aspect-Test";

    protected pointcut traceOperations(): execution(* au.com.example.test.**.testMethod(..));

    protected void log(String msg)
    {
        Log.i(TAG, msg);
    }
}

Run and Verify

Once again run the application and verify in LogCat that the aspect tracing has worked.

Sample app 2

LogCat tracing

The Sample Code

You can download the sample code for this example, aspect-lib-example_2.zip from GitHub. Follow the same instructions as for the previous example for running the sample app.

Conclusion

Now the aspect library project is reusable in other applications. An application would just need to include the library and then override the abstract pointcut to implement a concrete pointcut that is specific to it.

In the last part of this article, we will add another library to the application and show how to apply the aspects to it as well.

Reusable Aspect Library for Android, Part 1

There are various projects / tutorials / blogs out there about how to integrate AspectJ into the Android development process. They generally show you how to setup an application project to use AspectJ, with the aspects in the project itself.

However the way I tend to use AspectJ in Java projects is to try to put them into reusable libraries so that they can be applied to multiple projects. After all they are supposed to be used for cross-cutting concerns which are common to many applications. Searching the internet, I did not manage to find much information about how to do this in Android.

So here are some examples of one solution I found when using Eclipse (Windows version). If  you are not already familiar with creating and setting up Android projects in the Eclipse IDE, and with using AspectJ, have a look at the documentation for Android and AspectJ.

These are the requirements for the samples:

Note that the Android tools tend to be a bit brittle, so different versions may have changes (and bugs). So the examples may not work if you are using a different version.

Also I had the following design goals in mind:

  • keep it as simple as possible
  • stick to using Android libraries


With Eclipse you can put code in separate Java projects and either reference them from an Android application either as a project or a jar, e.g. create a ‘glue’ Android library that references a Java library.
While this might work in Eclipse, it would make things much more complicated if I wanted to use another build system (e.g. Ant) to build the application.

Scenario 1: Self-Contained Aspect Library

In the first example, we will create an android library that contains all the aspect code, and use it to apply the aspects to some code in an application.

Here are some instructions on setting up an Android library with aspects, along with some sample code.

The Test Application

This is just a very simple app to demonstrate the aspects working.

1. Create a new Android application project and add some code that the aspects can intercept.


public class MainActivity extends Activity {

private Button testButton;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 testButton = (Button)findViewById(R.id.test_button);
 testButton.setOnClickListener(testButtonListener);
 }

private OnClickListener testButtonListener = new OnClickListener() {
 public void onClick(View v)
 {
 // invoke the method to be traced
 testMethod();
 }
 };

 public void testMethod()
 {
 Toast.makeText(this, "Inside test method", Toast.LENGTH_SHORT).show();
 }

2. Add the AspectJ nature to the application project.

If you already know how to setup AspectJ in an Eclipse project, then you can skip the next bit …

To add the AspectJ nature to the application project, there are 2 ways of doing this:

a. Using the AJDT plugin
Right click on the project in the Package Explorer to bring up the context menu.

  • Click ‘Configure’
  • Click ‘Convert to AspectJ project’

Menu to convert to AspectJ project

b. Do it manually

  • Edit the ‘.projects’ file for the project.

Replace the java builder …

<buildCommand>
  <name>org.eclipse.jdt.core.javabuilder</name>
  <arguments>
  </arguments>
</buildCommand>

with the AspectJ builder …

<buildCommand>
  <name>org.eclipse.ajdt.core.ajbuilder</name>
  <arguments>
  </arguments>
</buildCommand>

and then add the AspectJ nature …

<nature>org.eclipse.ajdt.ui.ajnature</nature>

The edited file should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>ATest</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.ajdt.core.ajbuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>org.eclipse.ajdt.ui.ajnature</nature>
		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>
  • Add the AspectJ runtime jar to the classpath for the project.

The jar is named ‘aspectjrt.jar’ and it is probably a good idea to use the one that came with the AJDT plugin, which should be located under your Eclipse install at ‘plugin/org.aspectj.runtime_x.x.x’.

There are various ways of doing this, but if you have AJDT installed, the easiest way would be to add it as a library in your ‘Java Build Path’ dialog. In the ‘Java Build Path’ dialog, select the ‘Libraries’ tab, and then click the ‘Add Variable’ button. Then in the ‘New Variable Classpath Enty’ dialog that comes up, select the ‘ASPECTRT_LIB’ entry and click the ‘OK’ button.

Add aspectrt.jar as variable

To make the sample code a bit more portable, rather than doing it this way,  I’ve just copied ‘aspectjrt.jar’ to a directory named ‘lib’ in the project and added it to the classpath from there.

The Aspect library

This is the Android library project that will contain the aspects.

1. Create an Android library project

2. Add the AspectJ nature to the library project (the same as for the application project)

3. For these samples I am going to show a very common usage of AOP – tracing. So add some an AspectJ tracing code to an aspect file in the library project, with the pointcut configured to intercept some code in the application project.

public aspect TraceAspect {

    private final static String TAG = "Aspect-Trace";

    // pointcut to intercept a method in the application project
    protected pointcut traceOperations(): execution(* au.com.example.test.**.testMethod(..));

    before() : traceOperations() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        log("Entering [" + sig.toShortString() + "]");
    }

    protected void log(String msg)
    {
	Log.i(TAG, msg);
    }
}

4. Add the aspect library project as an Android library for the application project.

Add aspect library project to application

5. Also add the aspect library project to the AspectPath for the application. Do this in the ‘AspectJ Build’ dialog for the application project.

For the application project, right click the project in the Package Explorer to bring up the context menu.

Then either …

  • Click ‘Build Path -> Configure Build Path …’ to bring up the project properties dialog
  • Click ‘AspectJ Build’ in the side menu

or …

  • Click ‘AspectJ Tools -> Configure AspectJ Build Path …’

In the ‘AspectJ Build’ dialog, click the ‘Aspect Path’ tab. Then click the ‘Add Project…’ button and select the aspect library project.

Add aspect library to aspectpath of application

Run the application

Now run the application in your device or emulator, making sure that the code that you want to trace is invoked.

Sample app 1

For the sample app, just click the button ‘Click to test tracing’, and then check in LogCat that the aspect tracing has occurred.

LogCat tracing 1

The Sample Code

You can download the sample code for this example, aspect-lib-example_1.zip from GitHub.

Running the sample code:

  • Unzip the zip file containing the Eclipse projects.
  • Import the projects into your Eclipse IDE.
  • The sample projects have Android 4.0 (API level 14) as the Android build target. So you need to either have API 14 present in your Android SDK installation or change the build target for all the projects to another API version.
  • Optionally you may have to adjust any application or class paths to suit your development setup.
  • Build and run the sample application project.
  • Check LogCat to see if the aspect tracing is present.

Conclusion

The problem with this example is that the aspect library isn’t really all that reusable.

If you wanted to use the library in another application, chances are you would have to changed the pointcuts to match the code you want to intercept in the new application.

In the next part of this blog, we will make some improvements to it to make it more reusable.

Advanced Testing Tips for Android, Part 2

In part 1 of this article, I discussed some of the merits of Android testing on the emulator and rooted devices. In this concluding part, I’ll have a look at the software side of things.

Tracing

It is often useful to include tracing code while developing, one common usage is to trace the entry and exit of methods calls for example.

However it is generally recommended to remove tracing (and debug) logging from releases. This can be a hassle if these trace log statements sprinkled in your code. If you are using proguard to obfuscate your release version, then that is one option you can use to disable the tracing.

Another way is to use an AOP library like AspectJ to handle tracing instead (there are various examples of how to do this in Android available on the internet, just google it).

Some advantages of using AspectJ to handle tracing are:

  • The AspectJ tracing code could be put in separate library project, which may only be included in development builds (i.e. leave out the library in the build script for the release build).
  • Use of pointcuts is more configurable, as it can be used to trace as much or as little of your code as you require. This is useful to target the tracing to areas of your code when checking for errors.

Generally I would leave general method tracing disabled, but it is sometimes useful when running automated tests, e.g. when doing Continuous Integration or running Monkey, to trace the method flow in case there are crashes or other problems.

Monkey

This is another useful testing tool, but sometimes there are sections of your code that you don’t want to be run while testing with Monkey.

In this case, you can disable functionality for those sections of code when testing with monkey using ActivityManager.isUserAMonkey().

if (!ActivityManager.isUserAMonkey())
 {
    // only run if not running in Monkey
    doSomething();
 }

In my case I used this because the app I was working on had some functionality to run other apps on the device. If this code was run during Monkey testing, then Monkey would continue to run on the secondary app rather than the main app that I wanted to test.

Another example of it’s usage is in the Android API demos (to stop Monkey running any ‘dangerous’ code) :
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html

Accessory Apps for Testing

To assist in testing, it may be useful to write some additional apps to handle various accessory tasks:

  • configuration of the device before running tests
  • loading test data, for instance I wrote a simple app to load test contacts and SMS messages.
  • test for failures in intents passing, e.g. if the main app runs other apps using intents, you could use intents to run an app that deliberately fails to see how the main app handles it

Using load-time AOP to help testing and debugging

After reading this blog ‘Practical Introduction into Code Injection with AspectJ, Javassist, and Java Proxy‘, it reminded me how handy AOP tools like AspectJ are, in testing and debugging applications – particularly on servers.

How many times have you encountered a problem or bug in staging (or common test or reference) servers that you can’t reproduce in your own dev server? Ideally deployments should be consistent and reproducable so that this should never happen, but unfortunately in real projects that is not always the case.

Sometimes various issues can cause these differences:

  • manual configurations to the build process
  • continuous integration not used rigorously
  • different environmental settings on different server instances
  • different external services used in development, as opposed to a staging environment

Factors like these may lead to inconsistent builds or differing behaviour in different server environments.

I’ve found that using load-time weaving with AspectJ can be useful testing and debugging the application code on a staging server, without requiring any source code changes. The good thing is that because it doesn’t change the actual build artifacts on the file system (of course the code is changed when the affected classes are loaded!), you can remove the load-time weaving any time and revert back to the original code without having to do another build.

Here are some examples of what can be done to assist testing and debugging on a server that is not directly controlled by the developer. I’m assuming here that you are able to implement load-time weaving on the server.

Also if you are not familiar with AOP and AspectJ, else please read the AspectJ documentation or a book on AspectJ, such as the excellent AspectJ in Action.

Tracing

The generic introductory example for demonstrating how useful AOP is, seems to be tracing. The ability to add logging code to trace (program flow, method parameters and return value, etc) is very handy for debugging, particularly when using pointcuts to narrow the scope of the tracing to the sections of code that are problematic.

Here is a simple example with some test classes:

public class Customer {
  private String name;
  private String phone;
  private String address;

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getPhone() {
    return phone;
  }
  public void setPhone(String phone) {
    this.phone = phone;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
}

public class AccountService {

  public boolean addCustomer(Customer customer, String accountId, boolean isNewCustomer)
  {
    // real code to add customer to an account would be added here

    return true;
  }
}

For the tracing code, you can use the examples from the AspectJ programming guide or the book AspectJ in Action.

Then in a trace aspect class, use a pointcut to trace the code we’re interested in (in this case AccountService.addCustomer()).

pointcut traceOperations() : execution(* trace.blogexample.AccountService.addCustomer(..));

When the code is run, you might get some tracing, showing that the code was run and the parameters that were passed to the method in the pointcut.

Enter  [trace.blogexample.AccountService.addCustomer]
  [ This: trace.blogexample.AccountService@6262937c]
  [Args: (trace.blogexample.Customer@35c0e45a,ABC123,true)]
Exit  [trace.blogexample.AccountService.addCustomer]

Even more useful is if you combine the logging code with reflection to trace not only simple values, but also the contents of objects that you are interested in.
For the above example you might get tracing that shows the fields of objects passed to the method as parameters.
Hopefully the info from the tracing may be helpful in fixing a bug or problem.

Enter  [trace.blogexample.AccountService.addCustomer]
  [ This: trace.blogexample.AccountService@1d5a0305]
  [Args: (trace.blogexample.Customer@377653ae[
  name=John Smith
  phone=1234567890
  address=1 Test Street
  ],java.lang.String@54cbf30e[
  value={A,B,C,1,2,3}
  offset=0
  count=6
  hash=1923891888
  ],java.lang.Boolean@442a15cd[
  value=true
  ])]
Exit  [trace.blogexample.AccountService.addCustomer]

As I’ve mentioned, you can target where the want the tracing to occur:

  • by setting the pointcut to trace in details the areas of code that are (or that you think are) causing problems,
  • where exceptions are being thrown (using an After throwing advice)

You can also build on the AOP tracing to do other useful things, for example I have an open source project (TestDataCaptureJ) that uses tracing to capture data to use in unit testing.

Data Validation

Instead of just tracing, you can go further by doing some data validation as well.

For instance you can insert some code to validate the parameters for a business method, and log any validation errors.

Another way is to use tools, such as Contract4J, to test compliance (checking for preconditions, postconditions and invariants in the business requirements). Use load-time weaving to hook in the Contract4J configuration for business methods that you want to test.

Method Replacement

Another technique I sometimes use is to replace methods invokations in the app with test code.
This involves creating an Around advice for a pointcut that includes a method we want to replace.
Then inside the Around advice you can:
1. run another method altogether

So instead of just invoking the original method …

Object returnValue = joinPoint.proceed(args);

invoke another method with the same return type.

Object returnValue = newMethod(args);

2. run with different parameters

Invoke the original method, but pass in different parameter values (of course the parameter types must match the method signature)

Object returnValue = joinPoint.proceed(newArgs);

So using method replacement techniques you can do things like:

  • inject your own data to test a particular scenario
  • proxy external calls, e.g. for a method that uses an external service, replace with a method that returns some test data we can use for diagnosis

Summary

These are just some ideas that I have found useful when testing and debugging issues in app development. They can be easily applied to your development environment, but using load-time weaving with AOP also makes them useful when you encounter problems in a server that is not directly under your control.

Of course these techniques do not replace your standard tools and debuggers, it is just another tool in your toolbox.

TestDataCaptureJ – Capture data for your unit tests

When you are writing unit tests or doing Test Driven Development (TDD) , one of tasks you may need to do is to get some data to run your tests with. If the data that you need is fairly simple then there are various options, such as manually creating the data classes, create some mocks, stick some data in a database, etc.

However if you need a large amount of complex data, then these options can become very time consuming. This was the situation that I’ve come across myself in various projects, in particular where I need to test a the checkout stage in a online shop using data from the basket. The development environment was running on a snapshot of the production database (therefore ‘real’ data) and for the test scenarios I need the data from the shopping basket with various combinations of basket items. However the basket items were quite complex: the basket item class had about 35 fields, some of which were other objects each containing maybe 5 – 15 fields themselves.

To get all the test data I needed to test all the scenarios, I created a tool which evolved into the TestDataCaptureJ open source project that is hosted on GitHub. This is a Java development tool that can be used in java (web) applications to capture data as you run through the test scenarios. The data is logged to file, but in a format that you can just cut and paste into your unit tests (or better still, into classes that are used by your unit tests).

As an example, in the tutorial I used the jpetstore sample app from the Spring Framework. This just meant configuring the jpetstore web app to run with TestDataCaptureJ, and then going through the checkout process with some items in the basket. Then I used the generated log in some unit tests that I wrote to test part of the checkout process. This is an example of the code that was generated:

public org.springframework.samples.jpetstore.domain.Account createParam1Account_org_springframework_samples_jpetstore_domain_Order_initOrder() {

org.springframework.samples.jpetstore.domain.Account account0 = new org.springframework.samples.jpetstore.domain.Account();
account0.setUsername("j2ee");
account0.setPassword(null);
account0.setEmail("yourname@yourdomain.com");
account0.setFirstName("ABC");
account0.setLastName("XYX");
account0.setStatus("OK");
account0.setAddress1("901 San Antonio Road");
account0.setAddress2("MS UCUP02-206");
account0.setCity("Palo Alto");
account0.setState("CA");
account0.setZip("94303");
account0.setCountry("USA");
account0.setPhone("555-555-5555");
account0.setFavouriteCategoryId("DOGS");
account0.setLanguagePreference("english");
account0.setListOption(true);
account0.setBannerOption(true);
account0.setBannerName("");

return account0;
}

The tutorial also demonstrates some of the limitations of the tool as well.

Caveats

TestDataCaptureJ was really meant to handle data objects which are designed to hold data and follow JavaBean conventions, e.g.

  • objects are created using constructors
  • fields has setter methods using standard naming convention
    e.g. a field named ‘userAccountName’ would have a public setter method ‘setUserAccountName()’

Also to intercept the processing of the application in order to log the data, the test data required must be an object that is either passed to a method as a parameter, or returned from a method as a return value.

Therefore it can’t currently handle object where this isn’t the case, e.g.

  • object that are not created with constructors, e.g. if they are created using factory methods instead
  • fields without setter methods or setter methods that don’t follow the standard naming convention
  • static fields (just not implemented)
  • objects pass into methods as varargs

There is some configuration that

How it works

Basically this is just a glorified version of the common AspectJ tracing example, using weave time loading to intercept the data objects that we are interested in. Only instead of just logging the contents, there is a 2 stage process:

  1. use java reflection to store access the field data recursively and store it in some metadata classes
  2. log the data as java code to file

There is a explanation page in the documentation that goes into more detail.

Please have a look at the code (or better still, fork it and play around with it) or read the documentation if you think this might be useful to you.