Wiki

Clone wiki

groovy-extensions / Home

Welcome

Welcome to the Groovy Extension Points wiki!

This project exposes a way to customize a Java application by using the dynamic language Groovy; the following figure shows the mechanisms used:

Groovy Extension Points principles

The main idea of this project is the notion of extension points that you define on an existing Java application in order to give you, or your customers, the possibility to extend easily your application with Groovy script code (it could be also another scripting language). It's like a plugin mechanism, but I prefer the expression extension points like we can find it in UML, because the principle is to realize additional actions at certain points when the application runs.

A simple example

Let's take a simple example in which we want customize a discount calculation for a sale and with a customer identified. The firt thing we need is an instance of the class com.odelia.extensions.ExtensionsManager that manages a set of extension points. Thee are different ways to define extension points (please refer to the unit tests in this repository); below, at the Java application's startup, we define the extension point calculateDiscount with a Groovy closure returned by the script ExtensionPoints.groovy:

ExtensionsManager em = new ExtensionsManager();
em.defineGroovyScriptForExtensionPoint("calculateDiscount", new File("ExtensionPoints.groovy"));

The Groovy ExtensionPoints.groovy script content:

class LoyaltyProxyService {
    
    double getClientDiscount(def sale) {
        double discount = 0.0
        if (new Date().year - sale.client.dateOfBirth.year == 20)
            discount = 20
        discount
    }
}

def loyaltyService = new LoyaltyProxyService()

applyDiscount = { sale ->   
    sale.discount = loyaltyService.getClientDiscount(sale)
}

This script returns a Closure that will be attached to the calculateDiscount extension in order to be executed later. So, later in the application execution, this extension point can be triggered by calling the ExtensionsManager.executeExtensionPoint method, after the cashier has entered all the items:

Client client = new Client("Alice", formatter.parse("01/01/1992"));
        
Sale sale = new Sale(client);
sale.addItem("Item1", 11.0);
sale.addItem("Item2", 12.0);
sale.addItem("Item3", 13.0);
        
em.executeExtensionPoint("calculateDiscount", sale);

As you can see above, the Sale instance is passed to the executeExtensionPoint call, and then our Groovy closure will receive it; so, in the Closure, we can determine a discount amount depending on the client's age.
Of course, you can imagine something more complex like invoking a loyalty remote service.

Java and Groovy extension point implementations

In this project, an extension point can be implemented by a Java object, or by a Groovy closure defined inline or in a Groovy script (please, refer to the unit tests in this repository). But only Groovy extension point implementations can be combined together (see below).
A Java object is useful to use, when you need to set a default behavior for an extension point, that can be extended or overriden by other extension point implementations in Groovy.

Combining Groovy extension point implementations

There are two ways to combine Groovy extension point implementations:

  • by addition (see addGroovyScriptForExtensionPoint method), when you need to execute many extension point implementations in sequence
  • or by composition (see composeGroovyScriptForExtensionPoint method). The last one uses Closure composition, where a Closure passes its result to the next Closure (like in the Filter pattern).

Conclusion

Far from AOP techniques (extension points are like points cut and aspects), Groovy Extension Points is a simple approach to extend your applications. You must think in advance at what locations in applications you want to invoke your extensions points.
This project is more a proof of concept (it certainly lacks tests and controls), and can serve as a starting point for your own developments!

Updated