Tag Archives: adapters

Groovier Integration with Third Party Systems

A lot of the work I do deals with integration with a third party system. Each of these systems typically has their own API and mechanisms for handling errors. Often times writing some code to ‘wrap’ the API is required to make it easier to use from an application. Many times this ends up being an ‘adapter’ from the third-party API format to something more manageable and familiar to the application you are writing.

If you write this sort of thing in Java, you usually end up having a lot of duplicate code, specifically around error handling, that is hard to reuse without a lot of extra code. Lately, I have been using Groovy to solve these sorts of problems. The rest of the post shows a few ways I have learned to use Groovy to solve these problems in a better way. The result is simpler, more readable code.

Groovy Closures for Error Handling

Have you ever written this around a few methods?


try {
    // Some code in here
}
catch (APIException e) {
    log.error(e.getMessage(), e);
    throw new WrappedException(e);
}
finally {
    // cleanup here
}

Using Groovy’s Closures, this can be written as a single closure to do the error handling. Doing error handling this way is much simpler and allows the code to be reused easily.


// Definition of error handling closure
def errorHandling = { Closure c ->
    try {
        c()
    }
    catch (Exception e) {
        log.error(e.getMessage(), e);
        throw new WrappedException(e)
    }
    finally {
        // cleanup here
    }
}

// Code with error handling
errorHandling {
    // Some Code in here
}

For those not familiar with Groovy’s closures, let me explain what is happening here. The errorHandling variable is defined as a closure and is invoked around the code. This closure in turn takes a closure (function or code block in other languages) as a parameter. The error handling routine provides the stock error handling through the standard try catch syntax. Inside the try block, it invokes the closure that the user passed in. This allows the same error handling logic to be reused with the code to run being dynamically provided by the caller.

Groovy Categories for Mapping

Another problem is adapting between types in your application and types in the third party application. This is further complicated when dealing with collections of objects. Consider the following Java code to map from one system to another:


// Assumes some object instance 'util' is provided to map between object types.

// Given an input of InternalObject internal
List<InternalObject> list = new ArrayList<InternalObject>();
List<ExternalObject> results = api.operation(util.mapToExternal(input);            
for (ExternalObject o: results) {
    list.add(util.mapToInternal(o));
}
return list;

Instead of defining mappings as methods in some utility class, Groovy categories can be used to provide a more readable syntax.


// Category definition
class MappingCategory {
    static List<InternalObject> toInternalList(List<ExternalObject> o) {
        o.collect { toInternal(it) }
    }
    
    static InternalObject toInternal(ExternalObject from) {
         // Map from External to Internal
    }

    static ExternalObject toExternal(InternalObject from) {
         // Map from Internal to External
    }
}

// Code using the category. Input object is 'input'
use (MappingCategory) {
    api.operation(input.toExternal()).toInternalList()
}

The groovy category essentially adds dynamic methods to both the InternalObject and ExternalObject. The definition of the category has static methods which take one or more parameters. The first parameter is the class that the method should be added to. When the new method is invoked, the object it is invoked on is always added as the first parameter.

Also being used here is the list ‘collect’ method. This replaces what needed to be done in Java with creating a new list, looping over each item, converting it and adding it to the new list. The collect method does this in a single step by using a closure that converts the object to a new format. The result is a new list with the objects in the new format but in a single line of code.

Putting it all Together

Using this category can also be combined with the error handling closure that was previously introduced. Consider the following updated version of the error handling closure.


// Definition of error handling closure
def errorHandling = { Closure c ->
    try {
        use (MappingCategory) {
            c()
        }
    }
    catch (Exception e) {
        log.error(e.getMessage(), e);
        throw new WrappedException(e)
    }
    finally {
        // cleanup here
    }
}

With the previously defined error handling closure and category to handle the mappings, we can finally create a very minimal and readable adapter between our system and the third party system. Consider the following operation that uses the third party API. The input and output takes objects in the internal format.


public List<InternalObject> operation(InternalObject internal) throws WrappedException {
    errorHandling {
        return api.execute(internal.toExternal()).toIncidentList()
    }
}

Groovy’s closures allow error handling to be defined more easily and centralized in a single location where the code can be reused. Groovy’s categories allow data transformations to be done in a more readable fashion. The result is code that is easier to read and use.