GContracts 1.1.3 Released!

I am proud to announce that GContracts 1.1.3 has just been released and is available now in the Central Maven repository [0] and at Github [1]. The release includes bug fixes and advanced support Spring bean classes annotated with GContracts' annotations.

Concrete AssertionError types

In parallel with @Invariant, @Requires and @Ensures GContracts 1.1.3 provides separate exception types which all are descendants of AssertionError and I guess do not need further explanation: ClassInvariantViolation, PreconditionViolation and PostconditionViolation.

Advanced Support for Spring Beans

One of the problems with GContracts is its lack of compatibility especially with Grails artifact classes, i.e. controllers, services, domain classes etc. This topic has been brought to me a few times and if you just want to apply let's say class invariants on Spring bean classes the Spring application container's initialization lifecycle can quickly become your enemy. Let's consider the following service:
 
@Invariant({ anotherService != null })
class MyService {

    def anotherService

    static transactional = true

    // ...
}
 
MyService is a simple Grails service class, annotated with a class invariant which ensures that the reference to anotherService will never be null, during the entire life-time of the MyService bean. Sadly enough, whenever the Spring application container tries to create a new instance of a MyService bean it fails because GContracts checks the class invariant directly after the object's constructor has completed successfully. By that time, the Spring application container is not yet done with object construction. From a theoretical perspective throwing a ClassInvariantViolation in this place is completely reasonable since an object's class invariant needs to be fulfilled by the object instance during its entire life-time. But from a practical perspective, this is kind of pain. It means that you have to duplicate the class invariant to all methods in the service class, e.g.
 
// avoid invariant checks during construction
class MyService {

    def anotherService

    static transactional = true

    @Requires({ anotherService != null })
    def myServiceMethod()  {
        // ...
    }

    @Requires({ anotherService != null })
    def yetAnotherServiceMethod()  {
        // ...
    }
}
 
It is not that Design by Contract can not be applied here, it is that Spring simply does define its own rules for object creation and destruction, meaning that whenever an object is created with its constructor the initialization process is not done in the case of the Spring application container. This circumstance confuses programmers who simply want to apply DbC on their bean classes without thinking about Spring initialization mechanisms and GContracts assertion injection. GContracts 1.1.3 is the starting point for a bunch of features which are targeted to iron out such integration issues with Spring/Grails applications. Of course it might be questionable whether it makes sense to focus primarily on the Spring framework, but that has been a practical decision (GContracts is for Groovy, Grails uses Groovy, Grails uses Spring...). Furthermore, I tried to make the integration as light as possible without actually introducing a classpath dependency on Spring framework classes. The first feature which comes with 1.1.3 is a solution for the problem described above: class invariant checks on Spring beans. Henceforth, GContracts will not make class invariant checks on Spring beans during constructor calls, but will create a synthetic @PostConstruct method which overtakes the class invariant check. Since GContracts has no mechanism to know that the given class is a Spring-managed class at runtime, programmers need to annotate their artifact classes with appropriate stereotype annotations [2], e.g. a service class with @Service, a controller with @Controller, etc.
 
@Service
@Invariant({ anotherService != null })
class MyService {

    def anotherService

    static transactional = true

    // ...
}
 
The @Service stereotype annotation above triggers GContracts' "Spring compliance mode". Whenever the service bean above has been constructed by the Spring application container it will automatically check the class invariant. The programmer clearly needs to make a compromise in this case, because the class invariant won't be checked after a construction call anymore (e.g. in a test-case where the programmer simply creates an instance of this service class). But this is a consequence of outsourcing object creation to the application container. Hint: GContracts supports the -ea/-da VM parameters [3] which you can use to deactivate assertion checking during application execution, whereas activating assertion checking only during test-cases.

Changes

ISSUE-25: better support for Spring component classes with class invariants ISSUE-24: wrong class invariant placement with inherited invariant ISSUE-23: @Requires on constructor with super statement causes compilation error ISSUE-22: Separate Exception Types for Pre-, Postconditions and Class Invariant ISSUE-17: remove direct reference to PowerAssertionError

[0] GContracts 1.1.3 in Central Maven Repository
[1] GContracts at Github
[2] Spring Stereotype Annotations and Classpath Scanning
[3] GContracts VM Parameter Support
Flattr this