Archive for the ‘AOP’ Category.

AOP Custom Contract: ListNotEmptyAttribute

So I have a List and I need to make sure that the list has at least one value when it is passed in. If the list is empty, I should throw and exception. Here is an example of what the code would look like if you did NOT use an aspect:

using System;
using System.Collections.Generic;

namespace CustomContractsExample
{
    public class People
    {
        private readonly List<Person> _People;

        public People(List<Person> people)
        {
            if (people == null)
                throw new ArgumentNullException("people", "The list cannot be null.");
            if (people.Count == 0)
                throw new ArgumentException("people", "The list cannot be empty.");
            _People = people;
        }

        public List<Person> List
        {
            get { return _People; }
        }
    }
}

Note: My use case is not actually a People object with a List. It is instead something proprietary for my company and a far more valid use case. I am using the People class for simplicity in demonstration only.

I decided to handle this precondition checking not in the methods, but in an Aspect. Particularly, by using a PostSharp LocationContractAttribute. I recently wrote a post about this here:
AOP Contracts with PostSharp

So we need to create a new custom contract as I didn’t find one written by PostSharp. At first, I wondered why not. Why not create a quick generic attribute like this:

using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public class ListNotEmptyAttribute<T> : LocationContractAttribute, ILocationValidationAspect<List<T>>
    {
        new public const string ErrorMessage = "The List<T> must not be empty.";

        protected override string GetErrorMessage()
        {
            return "The List<T> must not be empty: {2}";
        }

        public System.Exception ValidateValue(List<T> value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (value.Count == 0)
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

Well, the reason is because C# doesn’t support generic attributes. I get this error at compile time:

A generic type cannot derive from ‘LocationContractAttribute’ because it is an attribute class

This is a tragedy. What makes it more of a tragedy is that I could do this if I wrote directly in IL. It is simply a compiler limitation for C#. Arrrgggss!!!! Good thing MSBuild is going open source at https://github.com/Microsoft/msbuild. Hopefully, the DotNet team, or some interested party such as PostSharp, or maybe me, contributes a few changes to MSBuild and removes this limitation.

As for now, List also implements IList, so I will revert to using that. IList provided a workaround for this use case, however, such a work around won’t always be available.

using System.Collections;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public class ListNotEmptyAttribute : LocationContractAttribute, ILocationValidationAspect<IList>
    {
        new public const string ErrorMessage = "The List must not be empty.";

        protected override string GetErrorMessage()
        {
            return "The list must not be empty: {2}";
        }

        public System.Exception ValidateValue(IList value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (value.Count == 0)
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

Now here is the new People class. See how it is much cleaner.

using System.Collections.Generic;

namespace CustomContractsExample
{
    public class People
    {
        private readonly List<Person> _People;

        public People([ListNotEmpty]List<Person> people)
        {
            _People = people;
        }

        public List<Person> List
        {
            get { return _People; }
        }
    }
}

The constructor is much cleaner and easier to read.

Also, my unit tests pass.

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CustomContractsExample;

namespace CustomContractsExampleTests
{
    [TestClass]
    public class PeopleTests
    {
        // Arrange
        private const string Firstname = "Jared";
        private const string LastName = "Barneck";

        [TestMethod]
        public void TestNewPersonWorks()
        {
            var person = new Person(Firstname, LastName);
            var list = new List<Person> { person };
            var people = new People(list);

            Assert.IsNotNull(people);
            Assert.IsFalse(people.List.Count == 0);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfFirstNameNull()
        {
            new People(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameNull()
        {
            new People(new List<Person>());
        }
    }
}

Maybe PostSharp can pick this up my ListNotEmptyAttribute and add it to their next released version.

AOP Contracts with PostSharp

So, I’ve been using Aspect Oriented Programming for a while. My company has a license for PostSharp. Recently I started using it more, in particularly, I started using the Contracts feature for checking the parameters of my methods. This is called precondition checking. Read more here: PostSharp Contracts

Here is a basic example of precondition checking. Imagine a Person class where the firstName and lastName should throw an exception if null, empty, or whitespace.
Your code might look like this:

using System;

namespace CustomContractsExample
{
    public class Person
    {
        private readonly string _FirstName;
        private readonly string _LastName;

        public Person(string firstName, string lastName)
        {
            // Validate first name
            if (string.IsNullOrWhiteSpace(firstName))
                throw new ArgumentException("Parameter cannot be a null, empty or whitespace string.", "firstName");

            // Validate last name
            if (lastName == string.Empty)
                throw new ArgumentException("Parameter cannot be an null, empty or whitespace string.", "lastName");

            // Initialize fields
            _FirstName = firstName;
            _LastName = lastName;
        }

        public string FirstName
        {
            get { return _FirstName; }
        }

        public string LastName
        {
            get { return _LastName; }
        }
    }
}

Ugh! Those lines to validate and throw exceptions are UGLY! Not to mention redundant. How many times might you write this same code. Probably over and over again. Of course this breaks the Don’t Repeat Yourself (DRY) principle.

Now, install PostSharp.Patterns.Model from NuGet.
(Note 1: This also installs PostSharp and PostSharp.Patterns.Common.)
(Note 2: This requires a paid license but is well worth it).

Looking at the Contracts, we particularly are interested in this one:

RequiredAttribute

RequiredAttribute is an attribute that, when added to a field, property or parameter, throws an ArgumentNullException if the target is assigned a null value or an empty or white-space string.

Here is the same class using PostSharp.Aspects.Contracts.

using PostSharp.Patterns.Contracts;

namespace CustomContractsExample
{
    public class Person
    {
        private readonly string _FirstName;
        private readonly string _LastName;

        public Person([Required]string firstName, [Required]string lastName)
        {
            _FirstName = firstName;
            _LastName = lastName;
        }

        public string FirstName
        {
            get { return _FirstName; }
        }

        public string LastName
        {
            get { return _LastName; }
        }
    }
}

Now, doesn’t that looks much nicer.

Yes, it does.

One issue:

It throws an ArgumentNullException if the string is empty or WhiteSpace. To me this is “Ok” but not preferred. If the data is not null, we shouldn’t say it is. Looking at the RequiredAttribute code, it is doing this:

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (!string.IsNullOrWhiteSpace(value))
                return null;
            return CreateArgumentNullException(value, locationName, locationKind);
        }

It really should be doing this.

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return (Exception)this.CreateArgumentNullException((object)value, locationName, locationKind);
            if (string.IsNullOrWhiteSpace(value))
                return (Exception)this.CreateArgumentException((object)value, locationName, locationKind);
            return (Exception)null;
        }

We can easily roll our own class to fix this bug.

using System;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public sealed class StringRequiredAttribute : LocationContractAttribute, ILocationValidationAspect<string>
    {
        protected override string GetErrorMessage()
        {
            return (ContractLocalizedTextProvider.Current).GetMessage("RequiredErrorMessage");
        }

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (string.IsNullOrWhiteSpace(value))
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

And here are my unit tests for what I expect. They all pass with my new StringRequired class.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CustomContractsExample;

namespace CustomContractsExampleTests
{
    [TestClass]
    public class PersonTests
    {
        // Arrange
        private const string Firstname = "Jared";
        private const string LastName = "Barneck";

        [TestMethod]
        public void TestNewPersonWorks()
        {
            var person = new Person(Firstname, LastName);
            Assert.IsNotNull(person);
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.FirstName));
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.LastName));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfFirstNameNull()
        {
            new Person(null, LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfLastNameNull()
        {
            new Person(Firstname, null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfFirstNameEmpty()
        {
            new Person(string.Empty, LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameEmpty()
        {
            new Person(Firstname, "");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfFirstNameWhiteSpace()
        {
            new Person("  ", LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameWhiteSpace()
        {
            new Person(Firstname, "     ");
        }
    }
}

AOP – Implementing a lazy loading property in C# with PostSharp

When developing in C#, you may have an object that contain properties that need to be initialized before they can be used. Think of a List<String> property. If you forget to initialize it, you are going to a NullReferenceException error. The List can be initialized as part of the constructor to solve this exception. However, maybe the List isn’t always used and you only want to load it if it needs to be used. So many people create a property that initializes iteself on first use. While this is not a bad idea, in C# it results in one line of code becoming at least six lines of code because you have to break out the auto property.

Here is the one line version verses the six line version (I can make it five lines if I put the private variable on the same line as the last bracket, which is a syntax I like with full properties).

List AddressLines { get; set; }
public List AddressLines
{
    get { return _AddressLines; }
    set { _AddressLines = value; }
}
private List<String> _AddressLines;

Wouldn’t it be nice if we could do this by only added single line of code, in this case an attribute? It can be that easy. Creating an instance on first use, or lazy loading, is a cross-cutting concern and can be extracted to an aspect using PostSharp. This article is going to show you how to do this.

It is assumed you have the following already installed and licensed:

  1. Visual Studio
  2. PostSharp

Step 1 – Create your Visual Studio Project

So to show you how this works, let’s get started.

  1. Create a sample Console Application project in Visual Studio.
  2. Add a reference to PostSharp.

Step 2 – Create an example class with properties

Ok, so let’s go ahead and create an example class called Address.

  1. Right-click on your project and choose Add | Class.
  2. Give the class file a name.
    I named this class Address.cs.
  3. Click OK.
  4. Add properties needed to store and address.
    Here my Address class working.
using System;
using System.Collections.Generic;

namespace ExampleAspects
{
    public class Address
    {
        public List AddressLines
        {
            get { return _AddressLines; }
            set { _AddressLines = value; }
        } private List<String> _AddressLines;

        public String City { get; set; }

        public String State { get; set; }

        public String Country { get; set; }

        public String ZipCode { get; set; }
    }
}

So our goal is to use Aspect-oriented programming to extract the lazy load something like this:

[LazyLoadAspect]
public List AddressLines { get; set; }

For me this is much clearer and more readable than the full property. Let’s make this happen in the next step.

Step 3 – Create the LazyLoadAspect

Ok, so let’s go ahead and create an example class called Address.

  1. Right-click on your project and choose Add | Class.
  2. Give the class file a name.
    I named this aspect class LazyLoadAspect.cs. Another good name might be InstantiateOnFirstUse or something.
  3. Make the class inherit from LocationInterceptionAspect.
  4. Override the OnGetValue method.
  5. Write code to get the value, check if it is null, and if null instantiate and set the value.
  6. Add a Type property that takes a type and implement that type if it is set, just in case you want to initialize using a child class. Otherwise how would you implement an interface.
using System;
using PostSharp.Aspects;

namespace Rhyous.ServiceManager.Aspects
{
    [Serializable]
    public class LazyLoadAspect : LocationInterceptionAspect
    {
        public Type Type { get; set; }

        public override void OnGetValue(LocationInterceptionArgs args)
        {
            args.ProceedGetValue();
            if (args.Value == null)
            {
                args.Value = Activator.CreateInstance(Type ?? args.Location.PropertyInfo.PropertyType);
                args.ProceedSetValue();
            }
        }
    }
}

Note: You may have a factory for creating your objects and you could replace the Activator.CreateInstance method with your factory method.

As discussed, replace the full property with this:

[LazyLoadAspect]
public List AddressLines { get; set; }

Step 4 – Prove your LazyLoadAspect works

Give it a try by creating an instance of Address in the Main method of Program.cs.

using System;
using Common.Aspects;
using PostSharp.Aspects;

namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            Address address = new Address();
            // NullReferenceException would occur here without the LazyLoadAspect
            address.AddressLines.Add("To: John Doe");
            address.AddressLines.Add("100 N 100 E");
            address.AddressLines.Add("Building 12 Floor 5 Suite 530");
            address.City = "SomeCity";
            address.State = "Utah";
            address.Country = "USA";
        }
    }
}

Well, you are done.

Please take time to look at how the code actually ended up using ILSpy or .NET Reflector.

Return to Aspected Oriented Programming – Examples

AOP – Implementing try catch in C# with PostSharp

I’ll be honest, I always cringe whenever I have to use try/catch. I do everything I can to avoid it. Besides being a resource hog, try/catch statements clutter code making it harder to read. So naturally I was excited when learning about Aspect-oriented programming (AOP) and PostSharp (the AOP library for C#) that try/catch statements are cross-cutting concerns and can be implemented as aspects.

It is assumed you have the following already installed and licensed:

  1. Visual Studio
  2. PostSharp

Step 1 – Create your Visual Studio Project

So to show you how this works, lets get started.

  1. Create a sample Console Application project in Visual Studio.
  2. Add a reference to PostSharp.
  3. Populate the Program.cs with an example exception as shown.
using System;
using Common.Aspects;

namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ThrowSampleExecption();
        }

        private static void ThrowSampleExecption()
        {
            throw new ApplicationException("Sample Exception");
        }
    }
}

Ok, now we have an example exception, lets show how we can catch this exception, log it, and continue.

Step 2 – Creating an exception aspect

  1. Right-click on your project and choose Add | Class.
  2. Give the class a name.
    I named my class ExceptionAspect.
  3. Click OK.
  4. Make the class inherit from OnExceptionAspect.
    Note: If you haven’t added a reference to PostSharp, you’ll need to do that now.
  5. Add a string property called Message.
  6. Add a Type property called ExceptionType.
  7. Add a FlowBehavior property called Behavior.
    The default value is FlowBehavior.Default.
  8. Override the OnException method.
  9. In the OnException method, create a message and log it.
    For this example, I will just log to the Visual Studio  Output window.
  10. In the OnException method, set the FlowBehavior to the Behavior property.
  11. Override the GetExceptionType method and configure it to return the ExceptionType property.
using System;
using System.Diagnostics;
using PostSharp.Aspects;

namespace Common.Aspects
{
    [Serializable]
    public class ExceptionAspect : OnExceptionAspect
    {
        public String Message { get; set; }

        public Type ExceptionType { get; set; }

        public FlowBehavior Behavior { get; set; }

        public override void OnException(MethodExecutionArgs args)
        {
            string msg = DateTime.Now + ": " + Message + Environment.NewLine;
            msg += string.Format("{0}: Error running {1}. {2}{3}{4}", DateTime.Now, args.Method.Name, args.Exception.Message, Environment.NewLine, args.Exception.StackTrace);
            Debug.WriteLine(msg);
            args.FlowBehavior = FlowBehavior.Continue;
        }

        public override Type GetExceptionType(System.Reflection.MethodBase targetMethod)
        {
            return ExceptionType;
        }
    }
}

Your ExceptionAspect class is complete and ready to use.

Step 3 – Apply the ExceptionAspect

  1. Add ExceptionAspect as an attribute to the ThrowSampleException method.
  2. Set the ExceptionType property to type of exception being thrown, which is an ApplicationException in this example.
  3. Set the Message property to hold a message.
  4. Set the Behavior property to FlowBehavior.Continue.
using System;
using Common.Aspects;
using PostSharp.Aspects;

namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ThrowSampleExecption();
        }

        [ExceptionAspect(ExceptionType = typeof(ApplicationException), Message = "An example exception.", Behavior = FlowBehavior.Continue)]
        private static void ThrowSampleExecption()
        {
            throw new ApplicationException("Sample Exception");
        }
    }
}

This is now complete. You have now implemented try/catch as an aspect.
You should take the time to look at your code with .NET Reflector or ILSpy to see what is really being done.
So here is the resulting code for the method accord to ILSpy.

  • Notice that our one line of code in the original method is in the try block.
  • Notice that in the catch block, the OnException method is called.
  • Notice that the catch block also has a switch statement based on the FlowBehavior to determine whether to continue or rethrow, etc.
// AspectExamples.Program
private static void ThrowSampleExecption()
{
	try
	{
		throw new ApplicationException("Sample Exception");
	}
	catch (ApplicationException exception)
	{
		MethodExecutionArgs methodExecutionArgs = new MethodExecutionArgs(null, null);
		MethodExecutionArgs arg_1F_0 = methodExecutionArgs;
		MethodBase m = Program.<>z__Aspects.m2;
		arg_1F_0.Method = m;
		methodExecutionArgs.Exception = exception;
		Program.<>z__Aspects.a0.OnException(methodExecutionArgs);
		switch (methodExecutionArgs.FlowBehavior)
		{
		case FlowBehavior.Default:
		case FlowBehavior.RethrowException:
			IL_55:
			throw;
		case FlowBehavior.Continue:
			methodExecutionArgs.Exception = null;
			return;
		case FlowBehavior.Return:
			methodExecutionArgs.Exception = null;
			return;
		case FlowBehavior.ThrowException:
			throw methodExecutionArgs.Exception;
		}
		goto IL_55;
	}
}

You now can implement pretty much any try/catch block as an Aspect using the ExceptionAspect.

Reusability

One of the main benefits of Aspects is that they take cross-cutting concerns and make them modular. That means that like class files, they are now reusable. Now it is easy to use, link to, or copy and paste your ExceptionAspect class into any other project.

Return to Aspected Oriented Programming – Examples

AOP – Tracing methods in C# with PostSharp

Suppose you are tasked with adding logging to trace when a method starts and when it ends. Now suppose that you are tasked to do this for every method in a project, lets say you have to do this for 1,000 methods scattered throughout all your objects. Every method included would have two lines of logging code, one at the start, one at the end. That means you have to add two lines of code per method or 2,000 lines of code.  Sure, you could extract the logging methods into a static or singleton making it “easier”, but in the end, you still end up with 2,000 lines of code, two per method.

Is adding 2,000 lines of code the right solution? No it is not. These lines of code can be distracting and can make a method less readable. A single line method becomes three lines. Your class files get bigger, especially if they are method heavy. Also, these lines of code break the SOLID principles in that 1) you are repeating yourself, and 2) your method no longer has a single responsibility as it is doing what it was design for and it is doing tracing, etc. It doesn’t have to be this way.

AOP can allow you to do the same task but have the code in a single place. Including spaces and brackets, the C# MethodTracingAspect file is only 36 lines of code and to implement this into all methods in a namespace an AspectInfo.cs file is used with only three lines of code.

Which would you rather deal with: 39 lines of code in two class files, or 2,000 lines of code spread throughout ever class file?

This document assumes you have the done the following already:

  1. Installed Visual Studio
  2. Installed PostSharp
  3. Licensed PostSharp

Note: While PostSharp has a free version, my examples will likely require the licensed version.

Step 1 – Create a new C# project for Aspects

  1. In Visual Studio, choose File | New | Project.
  2. Choose a Visual C# Console Application.
  3. Give the project a Name.
    Note: I named my project AspectExamples
  4. Click Ok.

Your project is now created.

Step 2 – Add a reference to PostSharp

  1. In Solution Explorer, right-click on your new project and choose Add Reference.
  2. In the Add Reference window, click to select the .NET tab.
  3. Locate PostSharp and click to highlight it.
  4. Click Ok.

You have now added PostSharp as a reference to your project.

Step 3 – Create an Aspect for method tracing

  1. Right-click on your project and choose Add | Class.
  2. Give the class a Name.
    Note: I named my version of this class MethodTraceAspect.
  3. Add a using reference to the PostSharp.Aspects namespace.
  4. Make the object inherit from OnMethodBoundaryAspect.
  5. Override the OnEntry method.
  6. Override the OnExit method.
  7. Add code to each method for logging to the Output window using Debug.WriteLine().
    Note: Obviously, you can use any logging library you software may use.
  8. Add code to make sure that methods inside methods are properly tabbed.

Here is my final class file.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using PostSharp.Aspects;

namespace AspectsExamples
{
    [Serializable]
    public class MethodTraceAspect : OnMethodBoundaryAspect
    {
        private static int _TabCount = 0;
        private static Stack<long> _StartTimeStack = new Stack<long>();

        public override void OnEntry(MethodExecutionArgs args)
        {
            Debug.WriteLine(GetTabs() + "Method started: " + args.Method.Name);
            _TabCount++;
        }

        public override void OnExit(MethodExecutionArgs args)
        {
            _TabCount--;
            Debug.WriteLine(GetTabs() + "Method completed:" + args.Method.Name);
        }

        private static String GetTabs()
        {
            string tabs = string.Empty;
            for (int i = 0; i < _TabCount; i++)
            {
                tabs += "\t";
            }
            return tabs;
        }
    }
}

You now have a modular Aspect that you can use to add method start, method end logging to any method in any C# project.

Step 4 – Implement the Aspect for method tracing

Implementing the Aspect for method tracing is accomplished by using an Attribute. The attribute can be added to a single method, a class, or a namespace.

We will use the following Program.cs file will demonstrate this.

using System;

namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            HelloWordMethod();
        }

        private static void HelloWordMethod()
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Option 1 – Adding the Aspect to methods

When adding this to method, you have to add it for each method.

  1. Add the MethodTraceAspect to the Main method.
  2. Add the MethodTraceAspect to the HelloWordMethod.
using System;

namespace AspectExamples
{
    class Program
    {
        [MethodTraceAspect]
        static void Main(string[] args)
        {
            HelloWordMethod();
        }

        [MethodTraceAspect]
        private static void HelloWordMethod()
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Ok, lets test this.

  1. Click Debug | Start Debugging to run the application in debug mode.
  2. Look at the Output and you should see the following lines.
Method started: Main
	Method started: HelloWordMethod
	Method completed:HelloWordMethod
Method completed:Main

Option 2 – Adding the Aspect to classes

When adding this to a class, you don’t have to add it for each method in the class.

  1. Add the MethodTraceAspect to the Program class.
using System;

namespace AspectExamples
{
    [MethodTraceAspect]
    class Program
    {
        static void Main(string[] args)
        {
            HelloWordMethod();
        }

        private static void HelloWordMethod()
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Ok, lets test this.

  1. Click Debug | Start Debugging to run the application in debug mode.
  2. Look at the Output and you should see the following lines.
Method started: Main
	Method started: HelloWordMethod
	Method completed:HelloWordMethod
Method completed:Main

Option 3 – Adding the Aspect to a namespace

When adding this to a namepsace, you don’t have to add it for each class or every method in each class. Instead it is automatically added to every method in every class in the namespace.

  1. Add the MethodTraceAspect to the namespace.
    Note: Notice the syntax is slight different for adding to a namespace than for a class or method.
using System;

[assembly: MethodTraceAspect]
namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            HelloWordMethod();
        }

        private static void HelloWordMethod()
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Ok, lets test this.

  1. Click Debug | Start Debugging to run the application in debug mode.
  2. Look at the Output and you should see the following lines.
Method started: Main
	Method started: HelloWordMethod
	Method completed:HelloWordMethod
Method completed:Main

Note: For real projects that aren’t just examples, it is a good idea to implement Aspects to a namespace in a separate file, such as an AspectInfo.cs file.

using Common.Aspects;
[assembly: MethodTraceAspect]
namespace AspectExamples {}

Congratulations, you have implemented an Aspect in C# using PostSharp.

Return to Aspected Oriented Programming – Examples

AOP – Implementing Role Based Security

You may want to implement role-based security, where you only allow users assigned a certain role to perform certain actions in an application. Many different classes in your code will need role-based security added to them. As it turns out, role-based security is a cross-cutting concern. Well, Aspect Oriented Programming (AOP) can help you modular such a role-based security structure.

Lets start with an example. Maybe you have a database filled with people (people being a list of user or person objects). You want to control the list of people. Now think of the Create, Read, Update, Delete (CRUD) pattern. Now turn those into four permissions.  Any role could potentially have or not have rights to create a person, read a person’s info, update a person’s info, or delete a person.  An admin user would likely have all of the four CRUD rights. A user would likely have CRUD rights for their own user, but just read rights for other users. Your design might have multiple levels of rights as well. You may want to provide multiple levels of read permissions. Think of any social network where you have more read rights if you are a friend of another Person.

If it was just for a Person object, you probably would implement an AOP-based solution. However, a large application will have dozens of classes around the Person class. It will have many entities besides Person and those entities have many surrounding data classes as well. What if you had to add code to over 100 class objects? Now you can really benefit from an AOP-based design.

Well, I am going to show you example to help get you started.
Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.

Prereqs

This example assumes you have a development environment installed with at least the following:

  • JDK
  • AspectJ
  • Eclipse (Netbeans would work too)

Step 1 – Create an AspectJ project

  1. In Eclipse, choose File | New | Project.
  2. Select AspectJ | AspectJ Project.
  3. Click Next.
  4. Name your project.
    Note: I named my project AOPRolePermissions
  5. Click Finish.
The project is now created.

Step 2 – Create a class containing main()

  1. Right-click on the project in Package Explorer and choose New | Class.
  2. Provide a package name.
    Note: I named my package the same as the project name.
  3. Give the class a name.
    Note: I often name my class Main.
  4. Check the box to include a public static void main(String[] args) method.
  5. Click Finish.
package AOPRolePermissions;

public class Main
{
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
	}
}

Step 3 – Create an object that needs Role-based security

For this example, I am going to use a simple Person object.

  1. Right-click on the package in Package Explorer and choose New | Class.
    Note: The package should already be filled out for you.
  2. Give the class a name.
    Note: I named mine Person.
  3. Click Finish.
  4. Add String fields for FirstName and LastName.
  5. Add a getter and setter for each.
package AOPRolePermissions;

public class Person
{
	// First Name
	private String FirstName = "";

	public String getFirstName()
	{
		return FirstName;
	}

	public void setFirstName(String inFirstName)
	{
		FirstName = inFirstName;
	}

	// Last Name
	private String LastName = "";

	public String getLastName()
	{
		return LastName;
	}

	public void setLastName(String inLastName)
	{
		LastName = inLastName;
	}
}

a

Step 4 – Implement example role-based code

For this I created the following objects:

  • Role
  • Permission
  • Permissions
  • FakeSession

The implementation of these is not important to this article, so I am not posting their code. However, you will see these classes if you download the project.

Step 5 – Implement an Annotation for  Role-based Security

Lets add an annotation to mark methods that should use role-based security.

  1. Right-click on the package in Package Explorer and choose New | Annotation.
    Note: The package should already be filled out for you.
  2. Give the annotation a name.
    Note: I named mine RoleBasedSecurity.
  3. Click Finish.
  4. Add a value for the permission type.
  5. Add a value for the Field name (in case the method is named completely different from the field).
  6. Set the Retention to RetentionPolicy.RUNTIME.
  7. Maybe add a comment that this annotation is for use by the Aspect (which we will create shortly).
package AOPRolePermissions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface RoleBasedSecurity
{
	Permission.Type value() default Permission.Type.All;
	String FieldName() default "";
}

Step 6 – Add the @RoleBasedSecurity annotation to methods

  1. In the Person class, add @RoleBasedSecurity(Type.Read) tag above the gettersof Person.
  2. In the Person class, add @RoleBasedSecurity(Type.Update) tag above the setters of Person.
package AOPRolePermissions;

import AOPRolePermissions.Permission.Type;

public class Person
{
	// First Name
	private String FirstName = "";

	@RoleBasedSecurity(value = Type.Read)
	public String getFirstName()
	{
		return FirstName;
	}

	@RoleBasedSecurity(Type.Update)
	public void setFirstName(String inFirstName)
	{
		FirstName = inFirstName;
	}

	// Last Name
	private String LastName = "";

	@RoleBasedSecurity(value = Type.Read)
	public String getLastName()
	{
		return LastName;
	}

	@RoleBasedSecurity(Type.Update)
	public void setLastName(String inLastName)
	{
		LastName = inLastName;
	}
}

Step 7 – Create an Aspect to check Role-based permissions

  1. Right-click on the package in Package Explorer and choose New | Other.
  2. Choose AspectJ | Aspect.
  3. Click Next.
    Note: The package should already be filled out for you.
  4. Give the Aspect a name.
    Note: I named mine SecureByRoleAspect.
  5. Click Finish.
package AOPRolePermissions;

public aspect SecureByRoleAspect
{

}

Step 7 – Add the pointcut and advice

  1. Add a pointcut called RoleBasedSecurityMethod.
  2. Implement it to work for any method called that is annotated with @RoleBasedSecurity: call(@RoleBasedSecurity * *(..)).
  3. Add a !within(SecureByRoleAspect) (to prevent an infinite loop).
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..)) && !within(SecureByRoleAspect);
}

You now have your pointcut.

Step 8 – Implement around advice to check for permissions

  1. Add around advice that returns an Object.
  2. Implement it to be for the RoleBasedSecurityMethod pointcut.
  3. Add code to check for permissions.
  4. Add a return statement.
package AOPRolePermissions;

import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;

public aspect SecureByRoleAspect
{
	pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..))	
									&& !within(SecureByRoleAspect);
	
	
	Object around() : RoleBasedSecurityMethod()
	{
		System.out.println("Checking permissions...");
		
		RoleBasedSecurity rbs = getRBSAnnotation(thisJoinPointStaticPart);

		// Use the FieldName if specified, otherwise guess it from the method name
		String field = (rbs.FieldName().equals("")) ? removeLowerCasePrefix(thisJoinPointStaticPart
				.getSignature().getName()) : rbs.FieldName();

		if (FakeSession.Instance.getCurrentRole().GetPermissions()
				.can(rbs.value(), field))
		{
			System.out.println(String.format(
					"Success: Role has permissions to %s field named %s.%s.",
					rbs.value(), thisJoinPointStaticPart.getSignature()
							.getDeclaringType().getName(), field));
			return proceed();
		}
		else
		{
			System.out
					.println(String
							.format("Failure: Role has insufficient permissions to %s field named %s.%s.",
									rbs.value(), thisJoinPointStaticPart
											.getSignature().getDeclaringType()
											.getName(), field));
		}

		return null;
	}

	private String removeLowerCasePrefix(String inString)
	{
		int startPoint = 0;
		for (int i = 0; i < inString.length(); i++)
		{
			if (Character.isUpperCase(inString.charAt(i)))
			{
				startPoint = i;
				break;
			}
		}
		return inString.substring(startPoint);
	}

	private RoleBasedSecurity getRBSAnnotation(JoinPoint.StaticPart inStaticPart)
	{
		RoleBasedSecurity rbs = null;
		Signature sig = inStaticPart.getSignature();
		if (sig instanceof MethodSignature)
		{
			// this must be a call or execution join point
			Method method = ((MethodSignature) sig).getMethod();
			rbs = method.getAnnotation(RoleBasedSecurity.class);
		}
		return rbs;
	}
}

You are done. Go ahead and run the program. You should get the following output.

Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson

Role Based Security with AOP Project Download

AOPRolePermissions.zip

Return to Aspected Oriented Programming – Examples

AOP – Logging method execution time  in Java with AspectJ

This is not a walk-thru. This is just an example AspectJ class.

Note: For logging, the log singleton which I previously posted is used, but of course you can hook this up to your own logging methods or just print to the console.

This class is intended to log when a method executes and when a method ends and include the time it took for a method to execute in nanoseconds. Methods inside methods are tabbed. This is an enhancement to this post: AOP – Logging all method calls and executions

package mainExample;

import java.util.Stack;
import org.aspectj.lang.JoinPoint;

public aspect AspectLogMethodExecution
{
	private int tabCount = 0;
	private Stack _StartTimeStack = new Stack();

	pointcut AnyMethod() : (call(* *.*(..)) || execution(* *.*(..)))
						&& !within(AspectLogMethodExecution)
						&& !within(Log);

	before() : AnyMethod()
	{
		PrintMethod(thisJoinPointStaticPart);
		tabCount++;
		_StartTimeStack.add(System.nanoTime());
	}

	after() : AnyMethod()
	{
		Long methodExecutionTime = EvaluateExecutionTime();
		tabCount--;
		PrintMethod(thisJoinPointStaticPart, methodExecutionTime);
	}

	private Long EvaluateExecutionTime()
	{
		Long methodExecutionTime = System.nanoTime() - _StartTimeStack.pop();
		return methodExecutionTime;
	}

	private void PrintMethod(JoinPoint.StaticPart inPart)
	{
		Log.WriteLine(GetTabs() + inPart);
	}

	private void PrintMethod(JoinPoint.StaticPart inPart, long inExecutionTime)
	{
		Log.WriteLine(GetTabs() + inPart + " Execution Time: "
				+ inExecutionTime + " nanoseconds");
	}

	private String GetTabs()
	{
		String tabs = "";
		for (int i = 0; i < tabCount; i++)
		{
			tabs += "\t";
		}
		return tabs;
	}
}

So if you have a simple Hello, World app, this is the log output.

execution(void mainExample.Main.main(String[]))
	call(void java.io.PrintStream.println(String))
	call(void java.io.PrintStream.println(String)) Execution Time: 112063 nanoseconds
execution(void mainExample.Main.main(String[])) Execution Time: 904636 nanoseconds

I ran it multiple times and the executions times were sporadic. I remember reading somewhere that System.nanoTime() in java was not extremely accurate, but it is accurate enough for this example.

 
Return to Aspected Oriented Programming – Examples

AOP – Logging all method calls and executions in Java with AspectJ

This is not a walk-thru. This is just an example AspectJ class.

Note: For logging, the log singleton which I previously posted is used, but of course you can hook this up to your own logging methods or just print to the console.

This class is intended to log when a method executes and when a method ends. Methods inside are tabbed.

package mainExample;

import org.aspectj.lang.JoinPoint;

public aspect AspectLogMethodExecution
{
	private int tabCount = 0;

	pointcut AnyMethod() : (call(* *.*(..)) || execution(* *.*(..)))
						&& !within(AspectLogMethodExecution)
						&& !within(Log);

	before() : AnyMethod()
	{
		PrintMethod(thisJoinPointStaticPart);
		tabCount++;
	}

	after() : AnyMethod()
	{
		tabCount--;
		PrintMethod(thisJoinPointStaticPart);
	}

	private void PrintMethod(JoinPoint.StaticPart inPart)
	{
		Log.WriteLine(GetTabs() + inPart);
	}

	private String GetTabs()
	{
		String tabs = "";
		for (int i = 0; i < tabCount; i++)
		{
			tabs += "\t";
		}
		return tabs;
	}
}

So if you have a simple Hello, World app, this is the log output.

execution(void mainExample.Main.main(String[]))
	call(void java.io.PrintStream.println(String))
	call(void java.io.PrintStream.println(String))
execution(void mainExample.Main.main(String[]))

Return to Aspected Oriented Programming – Examples

AOP – Encrypting with AspectJ using an Annotation

This is a continuation of AOP – Encrypting with AspectJ. It is expected you have read (or skimmed) that article first. This article uses the same project. The files in the project so far are these:

  • Encrypt.java
  • EncryptFieldAspect.aj
  • FakeEncrypt.java
  • Main.java
  • Person.java

The final version of EncryptFieldAspect.aj in the previous article is not exactly a “good” Aspect. The problem with it is that it isn’t very reusable. There is a one to one relationship between this Aspect and the field it encrypts. We want a one to many relationship where one Aspect works for encrypting many fields.

Another problem is there is nothing in the objects that would inform a developer that any Aspect Oriented Programming is occurring.

Step 9 – Making the Aspect reusable

Lets make the aspect reusable. Lets make one aspect with a single pointcut and a single around advice work for multiple setters in a class.

  1. In the Person class, add a forth field, DriversLicense. This field should also be encrypted.
  2. Add a getter and setter for the DriversLicense field.
  3. In the Main class, add sample code to set and later print out the DriversLicense field.
  4. In the EncryptFieldAspect, change it to work for all setters by using a * after the word set and making it work for any method that takes a string, not just the SSN setter.
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut encryptStringMethod(Person p, String inString):
	    call(void Person.set*(String))
	    && target(p)
	    && args(inString)
	    && !within(EncryptFieldAspect);

	void around(Person p, String inString) : encryptStringMethod(p, inString) {
		proceed(p, FakeEncrypt.Encrypt(inString));
		return;
	}
}

Ok, now it is reusable but we now have another problem. It is encrypting all the fields, including FirstName and LastName. It is definitely reusable, but now we need something to differentiate what is to be encrypted from what isn’t.

Step 10 – Create an Encrypt annotation

Lets add and use an annotation to mark setters that should use encryption.

  1. Right-click on the package in Package Explorer and choose New | Annotation.
    Note: The package should already be filled out for you.
  2. Give the annotation a name.
    Note: I named mine Encrypt.
  3. Click Finish.
  4. Maybe add a comment that this annotation is for use by the Encrypt Aspect.
public @interface Encrypt
{
	// Handled by EncryptFieldAspect
}

Step 11 – Add the @Encrypt annotation to setters

  1. In the Person class, add @Encrypt above the setSSN setter.
  2. Also add @Encrypt above the setDriversLicense setter.
	@Encrypt
	public void setSSN(String inSSN)
	{
		SSN = inSSN;
	}

 

	@Encrypt
	public void setDriversLicense(String inDriversLicense)
	{
		DriversLicense = inDriversLicense;
	}
}

Step 12 – Alter the EncryptFieldAspect to work for multiple objects

Well, now that it works for any setter in the Person object that is marked with @Encrypt, the next step is to make it work for any setter marked with @Encrypt no matter what object it is in.

  1. Remove any reference to Person. We don’t even need it or the parameter ‘p’.
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut encryptStringMethod(String inString):
		call(@Encrypt * *(String))
		&& args(inString)
		&& !within(EncryptFieldAspect);

	void around(String inString) : encryptStringMethod(inString) {
		proceed(FakeEncrypt.Encrypt(inString));
		return;
	}
}

Great, now let’s test it.

Step 11 – Test Using @Encrypt on multiple objects

Ok, let’s create a second object that has an ecrypted field to test this. Lets create a Credentials.java file with a UserName and Password fields, getters and setters. Of course the Password should be encrypted.

  1. Right-click on the package in Package Explorer and choose New | Class.
    Note: The package should already be filled out for you.
  2. Give the class a name.
    Note: I named mine Credentials.
  3. Click Finish.
  4. Add both a UserName and Password field.
  5. Add a getter and setter for both.
  6. Add the @Encrypt annotation above the setPassword setter.
package AOPEncryptionExample;

public class Credentials
{
	// UserName
	private String UserName;

	public String getUserName()
	{
		return UserName;
	}

	public void setUserName(String userName)
	{
		UserName = userName;
	}

	// Password
	private String Password;

	public String getPassword()
	{
		return Password;
	}

	@Encrypt
	public void setPassword(String password)
	{
		Password = password;
	}
}

Now lets create a Credentials object in the main() method and print out the values.

package AOPEncryptionExample;

public class Main
{
	public static void main(String[] args)
	{
		Person p = new Person();
		p.setFirstName("Billy");
		p.setLastName("Bob");
		p.setSSN("123456789");
		p.setDriversLicense("987654321");

		System.out.println("Person:");
		System.out.println("         FirstName: " + p.getFirstName());
		System.out.println("          LastName: " + p.getLastName());
		System.out.println("               SSN: " + p.getSSN());
		System.out.println("  Driver's License: " + p.getDriversLicense());
		System.out.println();

		Credentials c = new Credentials();
		c.setUserName("billybob");
		c.setPassword("P@sswd!");

		System.out.println("Person:");
		System.out.println("       UserName: " + c.getUserName());
		System.out.println("       Password: " + c.getPassword());
	}
}

Ok, test it. The output should be as follows:

Person:
         FirstName: Billy
          LastName: Bob
               SSN: #encrypted#123456789#encrypted#
  Driver's License: #encrypted#987654321#encrypted#

Person:
       UserName: billybob
       Password: #encrypted#P@sswd!#encrypted#

Well, now you have learned how to encrypt using Aspect Oriented Programming.

Here are a couple of benefits of encrypting with AOP.

  1. The crosscutting concern of security is now modular.
  2. If you wanted to change/replace the encryption mechanism, including the encryption method names, you can do that in a single place, the EncryptFieldAspect object.
  3. The code to encrypt any field in your entire solution is nothing more than an annotation, @Encrypt.
  4. The @Encrypt annotation can provide documentation in the class and in API documentation so the fact that encryption is occurring is known.
  5. You don’t have to worry about developers implementing encryption differently as it is all done in a single file in the same predictable manner.

Congratulations on learning to encrypt using AOP, specifically with AspectJ and Annotations.

What about decryption?

By the way, I didn’t show you how to decrypt. Hopefully I don’t have to and after reading you know how. Maybe in your project the design is that the getters return the encrypted values and you don’t need to decrypt. However, maybe in your design you need your getters to decrypt. Well, you should be able to impement a DecryptFieldAspect and a @Decrypt annotation for that.

If you use decrypt on the getter, the output is the same as if there were no encrypt/decrypt occuring. However, it is still enhanced security because the value is stored encrypted in memory and not as plain text in memory.

However, I have a version of the project that decrypts that you can download.

AOP Encryption example project Download

Download the desired version of the project here:

Return to Aspected Oriented Programming – Examples

AOP – Encrypting with AspectJ

Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.

Prereqs

This example assumes you have a development environment installed with at least the following:

  • JDK
  • AspectJ
  • Eclipse (Netbeans would work too)

Step 1 – Create an AspectJ project

  1. In Eclipse, choose File | New | Project.
  2. Select AspectJ | AspectJ Project.
  3. Click Next.
  4. Name your project.
    Note: I named my project AOPEncryptionExample
  5. Click Finish.
The project is now created.

Step 2 – Create a class containing main()

  1. Right-click on the project in Package Explorer and choose New | Class.
  2. Provide a package name.
    Note: I named my package the same as the project name.
  3. Give the class a name.
    Note: I often name my class Main.
  4. Check the box to include a public static void main(String[] args) method.
  5. Click Finish.
package AOPEncryptionExample;

public class Main
{
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
	}
}

Step 3 – Create an object with an encrypted value

For this example, I am going to use a Person object, and we are going to encrypt the SSN on that object.

  1. Right-click on the package in Package Explorer and choose New | Class.
    Note: The package should already be filled out for you.
  2. Give the class a name.
    Note: I named mine Person.
  3. Click Finish.
  4. Add String fields for FirstName, LastName, and SSN.
  5. Add getters and setters for each.
package AOPEncryptionExample;

public class Person
{
	// First Name
	private String FirstName = "";

	public String getFirstName()
	{
		return FirstName;
	}

	public void setFirstName(String inFirstName)
	{
		FirstName = inFirstName;
	}

	// Last Name
	private String LastName = "";

	public String getLastName()
	{
		return LastName;
	}

	public void setLastName(String inLastName)
	{
		LastName = inLastName;
	}

	// Social Security Number
	private String SSN = "";

	public String getSSN()
	{
		return SSN;
	}

	public void setSSN(String inSSN)
	{
		SSN = inSSN;
	}
}

Right now, SSN has no encryption. We don’t want to clutter our Person class with encryption code. So we are going to put that in an aspect.

Step 4 – Add sample code to main()

  1. Create in instance of Person.
  2. Set a FirstName, LastName, and SSN.
  3. Ouput each value.
public static void main(String[] args)
{
	Person p = new Person();
	p.setFirstName("Billy");
	p.setLastName("Bob");
	p.setSSN("123456789");

	System.out.println("FirstName: " + p.getFirstName());
	System.out.println(" LastName: " + p.getLastName());
	System.out.println("      SSN: " + p.getSSN());

}

If you run your project, you will now have the following output.

FirstName: Billy
 LastName: Bob
      SSN: 123456789

Step 5 – Create and object to Simulate Encryption

You don’t have to do full encryption, or any encryption at all for that matter, to test this. The important thing to realize is that you can configure how the value is stored in an object without cluttering the object with the encryption code.

I created a FakeEncrypt static object and will use this object as an example.

package AOPEncryptionExample;

public class FakeEncrypt
{
	public static String Encrypt(String inString)
	{
		return "#encrypted#" + inString + "#encrypted#";
	}
}

The goal is to passing in an SSN, 123-456-789, and have it return an encrypted value (or in this case a fake encrypted value), #encrypted#123-456-789#encrypted#.

Step 6 – Create an Aspect object

  1. Right-click on the package in Package Explorer and choose New | Other.
  2. Choose AspectJ | Aspect.
  3. Click Next.
    Note: The package should already be filled out for you.
  4. Give the Aspect a name.
    Note: I named mine EncryptFieldAspect.
  5. Click Finish.
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{

}

Step 7 – Add the pointcut

  1. Add a pointcut called SetSSN.
  2. Include two parameters, the Person object and the SSN string.
  3. Implement it with a call to void Person.setSSN(String).
  4. Add a target for the Person p.
  5. Add an args for the SSN string.
  6. Add a !within this class (to prevent an infinite loop).
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut setSSN(Person p, String inSSN):
	    call(void Person.set*(String))
	    && target(p)
	    && args(inSSN)
	    && !within(EncryptFieldAspect);
}

You now have your pointcut.

Step 8 – Implement around advice to replace the setter

  1. Add void around advice that takes a Person and a String as arguments.
  2. Implement it to be for the setSSN pointcut.
  3. Add code to encrypt the SSN.
  4. Add a return statement.
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut setSSN(Person p, String inSSN):
	    call(void Person.set*(String))
	    && target(p)
	    && args(inSSN)
	    && !within(EncryptFieldAspect);

	void around(Person p, String inSSN) : setSSN(p, inSSN) {
		p.setSSN(FakeEncrypt.Encrypt(inSSN));
		return;
}

You are done with this one method. Here is the output of running this program.

FirstName: Billy
 LastName: Bob
      SSN: #encrypted#123456789#encrypted#

So we aren’t exactly done because we have two issues that would be nice to resolve. First, the Aspect is not reusable and second, their is no way for a developer to know by looking at the Person object that the SSN should be encrypted. Both of these issue are resolved by using annotations and will be explained in the next article.

Continue reading at AOP – Encrypting with AspectJ using an Annotation

Return to Aspected Oriented Programming – Examples

AOP – Adding Advice before or after main() in Java with AspectJ

This is a very easy example of Aspect Oriented Programming. Lets add advice (code to run) before the main() executs and when main() finishes. You will see how without cluttering our Main class or our main() method, we can add modular code to run before or after main().

Prereqs

This example assumes you have a development environment installed with at least the following:

  • JDK
  • AspectJ
  • Eclipse (Netbeans would work too)

Step 1 – Create an AspectJ project

  1. In Eclipse, choose File | New | Project.
  2. Select AspectJ | AspectJ Project.
  3. Click Next.
  4. Name your project.
    Note: I named my project mainExample
  5. Click Finish.
The project is now created.

Step 2 – Create a class containing main()

  1. Right-click on the project in Package Explorer and choose New | Class.
  2. Provide a package name.
    Note: I named my package mainExample, the same as the project name.
  3. Give the class a name.
    Note: I often name my class Main.
  4. Check the box to include a public static void main(String[] args) method.
  5. Click Finish.
package mainExample;

public class MainExample
{
	static void main(String[] args)
	{
		// TODO Auto-generated method stub
	}
}

Step 3 – Create an Aspect object

  1. Right-click on the mainExample package in Package Explorer and choose New | Other.
  2. Choose AspectJ | Aspect.
  3. Click Next.
    Note: The package should already be filled out for you with “mainExample”.
  4. Give the Aspect a name.
    Note: I named mine StartEndAspect.
  5. Click Finish.
package mainExample;

public aspect StartEndAspect
{

}

Step 4 – Add a pointcut to the StartEndAspect

  1. Create a pointcut named mainMethod().
  2. Configure the pointcut to use “execution”.
  3. Configure the pointcut to be specifically for the “public static void main(String[] args)” method.
package mainExample;

public aspect StartEndAspect
{
    pointcut mainMethod() : execution(public static void main(String[]));
}

Note: Notice that to be specific for a method, you include everything but the parameter name.

Step 5 – Add before advice

  1. Add a before() statement for mainMethod().
  2. Have it simple write to the console a message such as “The application has started.”
package mainExample;

public aspect StartEndAspect
{
    pointcut mainMethod() : execution(public static void main(String[]));

    before() : mainMethod()
    {
        System.out.println("Application has started...");
    }
}

Step 6 – Add after advice

  1. Add an after() statement for mainMethod().
  2. Have it simple write to the console a message such as “The application has ended.”
package mainExample;

public aspect StartEndAspect
{
    pointcut mainMethod() : execution(public static void main(String[]));

    before() : mainMethod()
    {
        System.out.println("The application has ended...");
    }

    after() : mainMethod()
    {
        System.out.println("The application has ended...");
    }
}

So the advice is applied and even though there is not code in main(), the advice is applied and the console output is as follows:

The application has started…
The application has ended…

Congratulations you have learned one simple way to use Aspect Orient Programming for Java with AspectJ.
Return to Aspected Oriented Programming – Examples