Getting rid of null parameters with a simple spring aspect

What is the most hated and at the same time the most popular exception in the world? I bet it’s the NullPointerException.

NullPointerException can mean anything, from simple “ups, I didn’t think that can be null” to hours and days of debugging of third-party libraries (try using Dozer for complicated transformations, I dare you).

The funny thing is, it’s trivial to get rid of all the NullPointerExceptions in your code. This triviality is a side effect of a technique called “Design by Contract”.

I won’t go into much details about the theory, you can find everything you need on Wikipedia, but in the nutshell Design by Contract means:

  • each method has a precondition (what it expects before being called)
  • each method has a postcondition (what it guarantees, what is returned)
  • each class has an constraint on its state (class invariant)

So at the beginning of each method you check whether preconditions are met, at the end, whether postconditions and invariant are met, and if something’s wrong you throw an exception saying what is wrong.

Using Spring’s internal static methods that throw appropriate exceptions

(IllegalArgumentException), it can look something like this:

import static org.springframework.util.Assert.notNull;
import static org.springframework.util.StringUtils.hasText;

public class BranchCreator {
    public Story createNewBranch(Story story, User user, String title) {
        verifyParameters(story, user, title);
        Story branch = //... the body of the class returnig an object
        verifyRetunedValue(branch);
        return branch;
    }

    private void verifyParameters(Story story, User user, String title) {
        notNull(story);
        notNull(user);
        hasText(title);
    }

    private void verifyRetunedValue(Story branch) {
        notNull(branch);
    }
}

You can also use Validate class from apache commons instead of spring’s notNull/hasText.

Usually I just check preconditions and write tests for postconditions and constraints. But still, this is all boiler plate code. To move it out of your class, you can use many Design by Contract libraries, for example SpringContracts, or Contract4J. Either way you end up checking the preconditions on every public method.

And guess what? Except for Data Transfer Objects and some setters, every public method I write expects its parameters NOT to be null.

So to save us some writing of this boiler plate ocde, how about adding a simple aspect that will make it impossible in the whole application, to pass null to anything other than DTOs and setters? Without any additional libraries (I assume you are already using Spring Framework), annotations, and what else.

Why would I like to not allow for nulls in parameters? Because we have method overloading in modern languages. Seriously, how often do you want to see something like this:

Address address = AddressFactory.create(null, null, null, null);

And this is not much better either

Microsoft.Office.Interop.Excel.Workbook theWorkbook = ExcelObj.Workbooks.Open(openFileDialog.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

The solution

So here is a simple solution: you add one class to your project and a few lines of spring IoC configuration.

The class (aspect) looks like this:

import org.aspectj.lang.JoinPoint;
import static org.springframework.util.Assert.notNull;

public class NotNullParametersAspect {
    public void throwExceptionIfParametersAreNull(JoinPoint joinPoint) {
        for(Object argument : joinPoint.getArgs()) {
            notNull(argument);
        }
    }
}

And the spring configuration is here (remember to change the namespace to your project).

The “&&” is no error, it’s just && condition escaped in xml. If you do not understand aspectj pointcut definition syntaxt, here is a little cheat sheet.

And here is a test telling us that the configuration is succesfull.

public class NotNullParametersAspectIntegrationTest extends AbstractIntegrationTest {
    @Resource(name = "userFeedbackFacade")
    private UserFeedbackFacade userFeedbackFacade;

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionIfParametersAreNull() {
        //when
        userFeedbackFacade.sendFeedback(null);

        //then exception is thrown
    }

    @Test
    public void shouldNotThrowExceptionForNullParametersOnDto() {
        //when
        UserBookmarkDto userBookmarkDto = new UserBookmarkDto();
        userBookmarkDto.withChapter(null);
        StoryAncestorDto ancestorDto = new StoryAncestorDto(null, null, null, null);

        //then no exception is thrown
    }
}

AbstractIntegrationTest is a simple class that starts the spring test context. You can use AbstractTransactionalJUnit4SpringContextTests with @ContextConfiguration(..) instead.

The catch

Ah yes, there is a catch. Since spring AOP uses either J2SE dynamic proxies basing on an interface or aspectj CGLIB proxies, every class will either need an interface (for simple proxy based aspect weaving) or a constructor without any parameters (for cglib weaving). The good news is that the constructor can be private.

You May Also Like

ODEO new release

Recently, I released a new version 1.1.34 of ODEO (it's ODE tuned for Oracle and ServiceMix).You can check details (and downloads) here: http://top.touk.pl/confluence/display/top/ODEO.This version contains yet another set of fixes, which drive your BPE...Recently, I released a new version 1.1.34 of ODEO (it's ODE tuned for Oracle and ServiceMix).You can check details (and downloads) here: http://top.touk.pl/confluence/display/top/ODEO.This version contains yet another set of fixes, which drive your BPE...

Need to make a quick json fixes – JSONPath for rescue

From time to time I have a need to do some fixes in my json data. In a world of flat files I do this with grep/sed/awk tool chain. How to handle it for JSON? Searching for a solution I came across the JSONPath. It quite mature tool (from 2007) but I haven't hear about it so I decided to share my experience with others.

First of all you can try it without pain online: http://jsonpath.curiousconcept.com/. Full syntax is described at http://goessner.net/articles/JsonPath/



But also you can download python binding and run it from command line:
$ sudo apt-get install python-jsonpath-rw
$ sudo apt-get install python-setuptools
$ sudo easy_install -U jsonpath

After that you can use inside python or with simple cli wrapper:
#!/usr/bin/python
import sys, json, jsonpath

path = sys.argv[
1]

result = jsonpath.jsonpath(json.load(sys.stdin), path)
print json.dumps(result, indent=2)

… you can use it in your shell e.g. for json:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}

You can print only book nodes with price lower than 10 by:
$ jsonpath '$..book[?(@.price 

Result:
[
{
"category": "reference",
"price": 8.95,
"title": "Sayings of the Century",
"author": "Nigel Rees"
},
{
"category": "fiction",
"price": 8.99,
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"author": "Herman Melville"
}
]

Have a nice JSON hacking!From time to time I have a need to do some fixes in my json data. In a world of flat files I do this with grep/sed/awk tool chain. How to handle it for JSON? Searching for a solution I came across the JSONPath. It quite mature tool (from 2007) but I haven't hear about it so I decided to share my experience with others.