Custom collections in Groovy

Groovy allows to create custom collections the easy way. Moreover, a custom collection can support the Groovy collection API (all the additional methods that Groovy adds to Collection/List/Set).

The implementation is simple. Your custom collection is a decorator over the original collection. You provide a constructor accepting the collection you are wrapping. All method calls are delegated to the original collection with @Delegate annotation.

As an example, a custom list of Strings:

How to create your collection? You don’t have to call the constructor explicitly. Groovy as operator comes to the rescue:

Let’s see if it works:

Everything perfect!

For the curious, the culprit is DefaultGroovyMethods.asType(Collection col, Class clazz) method. It allows to cast plain Groovy collection to a custom implementation by calling the wrapping constructor.

Quest for (persistable) Groovy immutability

This is my first post about how to implement DDD concepts with Groovy and deliver them with Grails. My goal is to have real domain logic, without any (or as few as possible) dependencies on surrounding frameworks.

Grails is, at first glance, very pervasive and induces you to mix your business logic with concerns that should be treated separately. On the other hand, the framework is more modular with every release – which means you can disable some parts of it. Under the hood uses some popular libraries (which can be used directly by circumventing the framework).

This article is about implementing immutable Value Objects in Groovy and plugging in the persistence in a Grails application. First part discusses strategies of achieving immutability with Groovy. Second part describes how to persist our Value Object with in a relational database with Hibernate and in document-oriented database (MongoDB).

Create an immutable Value Object class

Value Objects, a building block of DDD should be implemented as immutable. Which options do we have in Groovy?

  • annotate your VO with @Immutable annotation
    • very straightforward, however, no customization options. You get a tuple/map constructor for free, but it sets all your VO properties to null by default. No way to specify mandatory properties and validate them.
  • declare all fields as final (with the default Groovy visibility). Fields will have getters but no setters. Then:
    • use @TupleConstructor
      • no boilerplate code
      • map constructor provided by this annotation is useless with final fields. It calls first the no-arg constructor and then tries to set fields with provided values. As there no setters, you will get a nice groovy.lang.ReadOnlyPropertyException exception.
      • all parameters of the tuple constructor have a default null value. As for @Immutable, no way to enforce mandatoriness.
    • implement custom constructor(s)
      • some boilerplate code, reduced with AST transformations GContracts
      • fully customizable

Example of an immutable Value Object with custom constructor:

Persist the FullName Value Object inside an aggregate

Our sample FullName VO is a part of a larger Person aggregate:

To persist it, I won’t use GORM (at least not directly).

Relational DB, Hibernate

I’m going to use external Hibernate mapping. With this approach my Person aggregate won’t be coupled at the source code level to any persistence configuration.

Hibernate imposes some restrictions on what your objects should provide in order to be persistable. The ORM must be able to instantiate an empty object. It requires a default constructor, although it can be protected.

At this point I have to make a small concession to Hibernate and add a default constructor1 to FullName:

protected FullName() {}

For filling the object with values read from the database, it doesn’t require to have setters. Hibernate is able to ‘reach’ a field through Java reflection (even if it’s final).

I map the VO as Hibernate component (an object mapped to the same table as the aggregate). As there are no setters, I instruct Hibernate to access VO properties directly with access="field":

As the gateway to the persistence I use a repository, an object that can provide the illusion of an in-memory collection (Eric Evans, Domain-Driven Design). As a rule of thumb, there is one repository per aggregate.

I don’t define an explicit interface; I’m going to use a duck type thorough the domain. The implementation is a delivery detail and I put it in the infrastructure layer.

By mapping the Person aggregate as an external Grails entity, it gets all persistence and query methods provided by GORM. However, the rest of domain and infrastructure code doesn’t notice them. The repository (PersonGormRepository) is the only component allowed to use the GORM API on Person.

Result: GORM becomes a plugin to the domain, totally unaware of it. There is only one place where the coupling application – GORM happens – in the implementation of the repository.

The code is pretty straightforward:

MongoDB

Mongo is a document-oriented database perfectly suited for storing objects modelled with composition – one document per each aggregate instance, together with all contained entities and value objects.

There is a MongoDB GORM plugin for Grails. I won’t use it, since I had to pollute my aggregate with mapping configuration (and it should be oblivious to the persistence). I’m going to use GMongo library, a Groovy wrapper over the official MongoDB driver. MongoDB for GORM offers no such thing like external MongoDB mapping.

My repository implementation uses quite a low-level API (compared to GORM). I don’t have to tweak my FullName value object. I can use all-property constructor when filling the VO from the Mongo document.

findById method is quite simple:

save method is more complex comparing with the Hibernate repository. It has to deal with the insert and update semantics.

Additionally, it’s in charge of generating numerical ids (in case of a relational database, we relied on the DB engine). I copied the implementation from the GORM MongoDB plugin source code. It uses a collection with single document containing the recently used ID. When obtaining it I use the Mongo atomic operation findAndModify, increasing the id by one and getting the increased value.

Summary

It is relatively easy to decouple your domain from persistence and make the latter a pluggable detail. You are leaving a well-trodden path of GORM, but the journey outside of it is not scary. You enter other safe routes guarded with decade old patterns and implementation techniques. Sometimes there are few signposts. You have to dig inside blogs and scarce documentation in order to move forward. Sometimes you just wander around and need to make some experiments in order to find the right way.

As reward you will get a cohesive object-oriented domain code that focuses only on one thing: solve problems of your/your customer’s business. Code that shifts data back and forth is strictly separated. Two worlds meet together at the repository frontier. And that’s fine, why should your business deal with database quirks?

Full source code

You find the complete source code in grails-ddd GitHub repo:
* master branch does not implement any persistence (yet)
* MongoDB and Hibernate (with H2 embedded database) repositories are implemented in mongo and hibernate branches, respectively.


  1. before adding a default protected constructor, I tried implementing a CompositeUserType and a custom tuplizer. Unfortunately, both need to create an empty object before filling it from the database result set. 

Groovy: Map vs Expando for dynamic data structures

with Expando…

def builder = new Expando(email: 'my email')
builder.make = { println email }
builder.make()

Result:
my email

with Map…

def builder = [email: 'my email']
builder.make = { println email }
builder.make()

Result:
groovy.lang.MissingPropertyException: No such property: email

Hamcrest matchers in Spock

Working with Spock we forget about a hidden gem – Hamcrest matchers. They are assertions turned into method objects. A matcher is usually parametrized with an expected value and is executed latel on the actual one.

When can we use it? For example in a table-driven specification with expected values in the table.

An expected value can be one of the following:

  • exact value
  • ‘not available’ text
  • any number

How can we express these assertions without Hamcrest?

then:
if (exactValue) {
    assert field == exactValue
} else if (notAvailable) {
    assert field == messageSource.getMessage('na', null, LocaleContextHolder.locale)
} else if (isNumber) {
    assert field.number
} else {
    assert false, 'Wrong test configuration'
}

where:
exactValue | notAvailable | isNumber
'12345'    | null         | null
null       | true         | null
null       | null         | true

Bufff…

  • there is a lot of boilerplate code
  • the specification is misleading – what does it mean that expected exactValue is null? Is it really null? Or simply this condition should not be checked?

How can we refactor this code using Hamcrest matchers?

then:
that field, verifiedBy

where:
verifiedBy << [
    org.hamcrest.CoreMatchers.equalTo('12345')
    notAvailable(),
    isNumber(),
]

...

def notAvailable() {
    org.hamcrest.CoreMatchers.equalTo messageSource.getMessage('na', null, LocaleContextHolder.locale)
}

def isNumber() {
    [
        matches: { actual -> actual.number },
        describeTo: { Description description -> 'should be a number' }
    ] as BaseMatcher
}

Result – shorter and more expressive feature method code.

You can find the full source code with mocked messageSource in this gist. For more information about Hamcrest matchers, check Luke Daley’s article.

Nesting categories in Groovy

Recently I discovered that Groovy categories can be nested. It means, you can inject a category into another one:

@Category(GroovyObject)
class FirstCategory {
    def method1() { }
}

@Category(GroovyObject)
@Mixin(FirstCategory)
class SecondCategory {
    def method2() {
        method1()
    }
}

@Mixin(SecondCategory)
class Mixee {
    def yetAnotherMethod() {
        method2()
    }
}

Before that ‘discovery’ I was injecting all categories into the final class. My code was not expressing the explicit dependency between the second and the first category:

@Mixin([FirstCategory SecondCategory)
class Mixee

Happy mixin’!