Groovy DSL and example notes to myself

February 22, 2016 Leave a comment

most of this stuff is already out there but i wanted to try and make sure i’d understood command chaining and other tricks

so first off we note that groovy allows your to drop ‘()’ off methods where there are multiple attributes (its still required for no arg method though)

def method1 ()
def method2 (arg1, arg2=null)
def method3 (Map map, arg1, arg2=null, ...)

//then
method2 (someArg) //is equivalent to
method2 someArg

//also with mixed named/unamed attributes groovy collects all named
// attributes as into a 1st map attribute of the method

//these two are equivalent
method3 (address: "the house", 0143 222222, street: "south close")
method3 address: "the house", street: "south close", 0143 222222

Also if your function returns itself or another function (or a closure) then the dot invocation is optional, for the compiler can read this when we drop the ‘.’

def method4 () {
    println "hello"
return this
}
method4().method4 () //is equivalent to 
method4() method4()

so this gives rise to some interesting examples of using groovy to work to build
DSL facilities.

so we’ll build an example up as we go of a groovy script to show some of the options, using a simple robot like DSL which can go in some direction, travel some distance, at some speed.

first i added a couple of static imports for enums that come later in the script

import static Direction.*
import static DistanceUnit.*
import groovy.transform.TupleConstructor

i then defined a couple of enums for a DistanceUnit and Duration as we are going
to embellish Numbers with some additional method facilities

//using static import to get 'left' and 'right' direction  enums -
//see static imports above
enum Direction {
    forward, backward, left, right
}

enum DistanceUnit {
 centimeters ('cm', 0.01),
 meters ('m', 1),
 kilometers ('km', 1000)

 String abbreviation
 double multiplier

 DistanceUnit (String abbr, double mult) {
 this.abbreviation = abbr
 this.multiplier = mult}
}

enum Duration {
    millisecond ('ms', 0.001),
    second ('s', 1),
    hour ('h', 60),
    day ('d', 60*24)

    String abbreviation
    double multiplier

    Duration (String abbr, double mult) {
        this.abbreviation = abbr
        this.multiplier = mult}
}


//define a symbol for hour in script, used when getting a speed = dist/dur
def h = Duration.hour

We the want to create a couple of classes for Speed and Distance, but use the @TupleConstructor annotation so that we can avoid having to type ‘new’ when we wish to create some instances of these classes. Also as we wish to have something like ‘5.km/h’ we need to overload the div operator for the Distance class and return a Speed from this operation.

//avoid having to use new in declaration
@TupleConstructor
class Distance {
    Number amount
    DistanceUnit unit

    //added div overload so that we can have distance over unit of time
    Speed div (Duration dur) {
        new Speed (amount, unit, Duration.hour)
    }

    String toString () {"$amount $unit"}
}
@TupleConstructor
class Speed {
    Number amount
    DistanceUnit unit
    Duration duration

    String toString () {"$amount $unit/$duration.abbreviation"}
}

Now through metaprogramming we can embellish Numbers with some methods to get a Distance like this

//add new meta method to Number- return the number (delegate) as instance of Distance
//global change to Number though - probably want to limit this using categories but forces us to inject
//and use groovy shell evaluate to do the assessment
Number.metaClass.getMeters = {new Distance (delegate, DistanceUnit.meters)}

However this is a global change to Number, and we probably wish to limit the scope of these methods, so lets define a Category instead like this

//limit the scope of added methods to use closure
class DistanceCategory {
    static Distance getCentimetres (Number num) {
        new Distance (num, DistanceUnit.centimeters)
    }

    static Distance getMeters (Number num) {
        new Distance (num, DistanceUnit.meters)
    }

    static Distance getKilometers (Number num) {
        new Distance (num, DistanceUnit.kilometers)
    }

    //short form
    static getCm (Number num) {
        getCentimetres(num)
    }

    static getM (Number num) {
        getMeters(num)
    }

    static getKm (Number num) {
        getKilometers (num)
    }
}

So using the above our first go for a DSL might be to be to define a function like this

def move1 (Direction dir, Distance d) {
        println "move1: moving $dir by $d"
}

//works because 3.meters calls the new metamethod to return instance 
//of Distance.  
//wrap in 'use' closure if using category class
move1 left, 3.meters

thats not too bad, we have removed the parentheses, and invoked the getMeters()
metamethod to return a Distance.

This will print ‘move1: moving left by 3 meters’ on the console

we can get a bit more readable by defining our move method like this. Ive used
the category class this time, not the global addition of meta method to Number.

//when a method call is made with a mix of named and no named params, then grooy puts all
//the named params into a map - as first param, and the rest as unnamed param in the order seen
//so define a new move like this

def move2 (Map m, Direction dir) {
    println "move2: moving $dir by $m.by at $m.at"
}

//use the move DSL and Category to add metamethods
use (DistanceCategory) {
move2 right, by: 3.meters, at: 5.km / h
}

This works as groovy collects the named parameters and drops them into the map,
and provides the remaining attributes, after that.

This writes ‘move2: moving right by 3 meters at 5 kilometers/h’ to the console.

However it would be nice to drop the ‘,’ and the : in the maps to make this more
readable. so here is the last trick using command chains (return a callable class – here a closure for next call)

//using command chains now
def move3 (Direction dir) {
    [by: {Distance dist ->
        [at: {Speed speed ->
            println "move3: moving $dir by $dist, at $speed"
        }]
    }]
}

use (DistanceCategory) {
    move3 right by 3.meters at 5.km / h
    //is the same as
    move3 (right).by (3.meters).at(5.km/h)
}

now when you provide the direction to the move3 method, it returns a map with key ‘by’ and a single closure as its value which is invoked with 3.meters. This
immediately returns another map with key ‘at’, and another closure which is
invoked with the 5km/h (using the overloaded Distance class to pass in a Speed as the attribute to the closure, the ‘h’ property was defined previously in the script binding above.

This can make your head explode walking through the tautology, but if you step through what the compiler sees you should be able to ‘see’ what this does.

Lastly I tried this

def func (arg = null) {
    println "got args as " + arg ?: null
    if (!arg) {
        println "setting up no arg closure in map"
        [by : { -> println "no args closure: hello william "}()]
    }
    else {
        println "setting up with arg closure in map"
        [by: { mapArg -> println "with args closure : $mapArg" }]
    }
}

//println "calling no args on func : "
func() by

//println "calling with args on func : "
println "calling args on func : "
func("someArg") by 3

In the first case we call ‘func’ with no args, and the function definition defines a single map with key ‘by’ that has a closure with no args. as no args as passed you have to add the ‘()’ in the first map to execute the returned closure. In the second case you provide an attribute for func, which sets up a map with key ‘by’ that takes an argument. so you can trigger this with the by 3 and call that closure when it returns.

All this best done with a clear head and step each bit through at a time.

You can also provide the DSL boilerplating in one class and separate the language script in another through using groovy shell evaluate and injecting the compiler customisers, static imports and extended base script to that the evaluate method inherits all the DSL
definition parts like this

def binding = new Binding (//add some variables etc ) 

def importCustomizer = new ImportCustomizer()
importCustomizer.addStaticStars Direction.name //etc 

def conf = new CompilerConfiguration()
conf.addCompilationCustomers (importCustomizer)
conf.scriptBaseClass = SomeDSLBaseScript.name  //specify the script base class

def shell = new GroovyShell (this.class.classLoader, binding, config)
shell.evaluate '''
      move left...
'''
Advertisements
Categories: Groovy, Uncategorized Tags:

Gradle and buildSrc and eclipse

I have been playing round with gradle and grails v3, there are a couple of things you need to know about gradle and eclipse. Especially if your going to write your extensions for gradle tasks etc.

one when you create a default gradle project in eclipse it doesn’t automatically build a buildSrc directory for you. But if you add one, gradle recognises this directory and tries to build the groovy/java files you might provide.

Moreover eclipse doesn’t recognise any such directory by itself and so the source code validation etc won’t really work. This is a bother if your want to use the IDE as your natural environment, which most do i suspect.

the default file structure you need to add is buildSrc/src/main/groovy or buildSrc/src/main/java respectively. Whilst gradle will build code in these folders, the IDE will treat this as a standard non source folder structure by default.

so if you try and add a class – it does what the IDE normally does and takes your class and the package and creates the file under the standard /src/main/groovy. I then had to move the it from there to the buildSrc sub directory.

The fix for this is to edit your build.gradle and explicitly add the buildSrc tree to the source sets and refresh all your dependencies (right click your project in explorer, and select gradle/refresh dependencies

sourceSets {
	main {
		java {
			srcDir 'src/main/java'
			srcDir 'src/main/groovy'
			srcDir 'buildSrc/src/main/java'
			srcDir 'buildSrc/src/main/groovy'
		}
		resources {
			srcDir 'src/resources'
			srcDir 'buildSrc/src/resources'
		}
	}
}

This will add the directory as a source folder in the project for you, and you can now create classes explicitly in these the new buildSrc folders.

Gradle automatically applies a default ‘build.gradle’ for the :buildSrc project if you don’t provide one which assumes the following defaults for you

apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
}

if you require additional flexibility you can provide your own in buildSrc/buildGradle, which is additive to this default, for example you might add

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.11'
}

see section 60 – Organising build logic in the user guide.

However, this not all you have to do. As your going to add your plugin or code in buildSrc you need to import the gradle api classes. like this for a simple dummy class

 
package com.softwood.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

class WillsTask extends DefaultTask {
	
	WillsTask () {
		group = 'Wills tasks'

		description = "one of wills tasks"
	}
	
	@TaskAction
	void start () {
		println "hello from Wills task"
	}

}

as the in buildSrc/src/main/groovy is now a source folder this throws allsort of warnings about not seeing the imports, (gradle my apply a default for you – but the IDE wont recognise that). So you have to go back to the build.gradle and add a compile dependency, like this

dependencies {
	compile gradleApi()
...
[/sourecode]

and refresh your dependencies again.  This gets the missing classes and adds them to your eclipse library 'Gradle Dependencies'

your buildSrc tree should now compile with no warnings and you can import your task definitions and use them in your build.gradle like this


import com.softwood.tasks.WillsTask

apply plugin: 'groovy'
apply plugin: 'eclipse'

....
task will (type : WillsTask) {
	doLast() {
		println "hello will"
	}
}

This now seems to work fine except that your main project dependencies now includes the gradleApi() classes. I haven’t figured how to setup dependencies just for the :buildSrc project and no other and keep them separated from the normal stuff in your project

within your build.gradle you can include a buildscript closure like this


buildscript {
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath gradleApi()
		classpath localGroovy()
		
	}
}

to add library dependencies to your :buildSrc classpath, in the above i’ve added the gradleApi() for example and the local groovy for the build (same as the implicit defaults). This works – but if the remove the ‘compile gradleApi()’ from your main dependencies your buildSrc folder will show failure to compile (as you have removed the libraries from ‘Gradle Dependencies’). But if you run the task ‘will’ it will all work.

I think this a deficiency with the interaction with eclipse and i need to query stack overflow/post a feature to get that resolved.

Categories: gradle Tags: , ,

Keep things where you can see stuff for grails projects

January 26, 2015 Leave a comment

Been having issues with a plugin project i’ve been trying to mend. This has led to exploration round plugins, gant scripts etc.

The latest one has been relating to gant script caching – when i added some script and got and error. So i removed the lines – and the cached version of the script with the error continues to being run. Not sure why. However short term quickfix is delete the script cache between calls

however on the way to finding the script cache and clearing it out – i’ve trod where others have been. One of the things that is a good thing to do is to update your conf/buildConfig.grooy file up at the top and add this little line

grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
grails.project.test.reports.dir = "target/test-reports"
grails.project.work.dir = "target/work" //add this line :where default work is stored

by default grails stores all the project work in .grails/.. This is not immediately obvious to newbies. by setting the work.dir inside your project – its easy to go looking and understand what the framework might be doing behind the scenes.

having the added the line, in GGTS select your project, right click and do Grails tools/Refresh dependencies

when you do that you’ll notice that the plugins are ‘re fetched’ and added in this case to the /target/work directory

Starting process on BTP055237/10.109.112.186
Loading Grails 2.4.4
|Configuring classpath
.
|Environment set to development
......
|Installing zip release-3.0.1.zip...
...
|Installed plugin release-3.0.1
.............
|Installing zip rest-client-builder-1.0.3.zip...
...
|Installed plugin rest-client-builder-1.0.3
..................
|Compiling 13 source files
.......
|Compiling 4 source files

this creates the work directory in your project like this

grails-work

when you run a script the compiled copy goes into the scriptCache as shown. However there is is an issue in the current grails2.4.4 where if you update the script after first running it, the script cache doesn’t update to the later groovy script you just saved. The tactical way round this (brute force) is to call the clean-all script which releases the GGTS lock on the closure, cleans the cache and you can then re-run the script which will recompile and recache. Bit painful but seems to work, without having to restart GGTS each time!

Categories: Grails, Grails Plugin Tags:

GPARS Actors and sleeping barber example

November 27, 2014 Leave a comment

started to look at the GPARS library and how to apply this into my programms – found an earlier example from Hamlet D’arcy, but it was out of date relative to latest GPARs constructs, and scheduling work at particular times

So i’ve had a go at relaunching it in new clothes. In order to simulate the waiting room i’ve used blocking queue of fixed size. Adding a customer will block when the waiting room is full – until someone (the barber takes one as his next customer)like this by sending a message to the actor

     barber << check client  //message to actor

in the second approach i've used the timer service to repeatedly schedule a message to a second barber ( not an actor ) which runs the action takes a client and reschedules itself for next ask

def barber2 = Executors.newScheduledThreadPool(1)
barber2.scheduleAtFixedRate({
	     println 'Barber2: Next customer please!'
		 Customer customer = waitingRoom.take()
		 println "${customer.name} gets a haircut at ${new Date().format('H:m:s')}" }
 as Runnable, 0, 5, TimeUnit.SECONDS)

the complete groovy script solution looks like this

package com.softwood.script

import groovy.transform.Immutable
import groovyx.gpars.group.DefaultPGroup

import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit


// create waiting room can't hold more than 12!  array queue of customers
def waitingRoom = new ArrayBlockingQueue(12)

/**
 * ArrayBlockingQueue filled with customers that need a haircut. 
 * And the barber is an executor service with a scheduled task to 
 * give haircuts. The number of threads in the scheduled thread 
 * pool is 1 because there's only one barber. The barber takes 
 * customers from the waiting room and cuts their hair once every 
 * 15 minutes. The call to waitingRoom.take() is blocking... if 
 * there is a customer ready then he is serviced immediately, and 
 * if one is not, then the call blocks until someone is available. 
 * Once thing to note... the waitingRoom has a size of 12... if a 
 * 13th customer is added then the calling code will either block 
 * until there is enough room or throw an exception. There is an 
 * API to do either case.
 */
final def group = new DefaultPGroup ()

//event driven actor model 
final def barberShop = group.reactor {message ->
	switch (message) {
		case Enter :
			println "${message.customer.name} enters and is waiting for a haircut"
			//add customer from message to the waiting room 
			waitingRoom.add (message.customer)
			break
		
		case "quit":
			println "called quit on barbershop - now new customers can come in"
			terminate()
			break
		
	}
}

// message to post on barberShop
@Immutable
class Enter {
	Customer customer
}

//customer for barbershop
@Immutable
class Customer {
	String name
}

//create a single barber - thread pool size of 1
final DefaultPGroup barberGroup = new DefaultPGroup (1)


println "barber opening shop"
//this model auto starts the barber
final barber = barberGroup.actor {
	loop {
		react {
			println "barber> asked to -> $it"
			println "barber> Next Customer Please!"
			Customer customer = waitingRoom.take()  //blocking call on waiting room
			println "barber> ${customer.name} gets a haircut at ${new Date().format('H:m:s')}"
		}
	}
}

def barber2 = Executors.newScheduledThreadPool(1)
barber2.scheduleAtFixedRate({
	     println 'Barber2: Next customer please!'
		 Customer customer = waitingRoom.take()
		 println "${customer.name} gets a haircut at ${new Date().format('H:m:s')}" }
 as Runnable, 0, 5, TimeUnit.SECONDS)


//add some customers to waiting room 
barberShop << new Enter(customer: new Customer(name: 'Jerry'))
barberShop << new Enter(customer: new Customer(name: 'Phil'))
barberShop << new Enter(customer: new Customer(name: 'Bob'))
barberShop << new Enter(customer: new Customer(name: 'Ron'))
barberShop << "quit"

//send 'message' to first barber 
barber << "check client  "

//barber.stop()
barber.join (20, TimeUnit.SECONDS)
println "customers in queue ${waitingRoom.size()}"
println "barber closing shop"

i’ve used @ immutable to construct a a thread safe message with thread safe ‘customer’ to pass to the waiting room

Categories: GPARS, Groovy Tags: , , ,

another silly gotcha grails 2.4 and plugin development with integration testing

November 15, 2014 Leave a comment

just wasted an hour getting the to the bottom of this. Hope this saves you some of that.

i just created a new Grails plugin project using grails 2.4.4 using GGTS. Plugin project gets created fine.

I created a couple of domain classes and tried to run an integration test.

hah first point. The grails documentation hasn’t caught up with what the code does. The documentation for unit tests still refers to extending the GroovyTestCase. However this is no longer what the code generator assumes you should do. Generating a integration test and you see the class now extends

import grails.test.spock.IntegrationSpec
..
class xxxSpec extends IntegrationSpec {

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() { 
    }
}

slightly annoying point is that spoc which is the default test runner assumes that you have the
when :, then:, expect: or similar blocks to be happy and the default template generation doesn’t do this for you. as a Newbie this can catch you out if you try and run tests.

however the key waste of time today was with a new plugin project. By default the plugin project doesn’t load the hibernate plugin in buildConfig.groovy. When you run your integration test it throws a weird error along the lines of


java.lang.IllegalStateException: Method on class [Domain class] was used outside of a Grails application

which throws you completely. What says you? of course i’m running grails that’s integration tests do for you. The answer is that missing hibernate plugin which causes the problem. I eventually found this on stackoverflow .

add the runtime plugin for hibernate in buildConfig and off you go

there are it appears other issues when using functional testing – but i’ve not got that far. part of the resolution to that requires you to include another plugin : remote-control plugin. I’ve included the link here as i’m bound to need it later

There is another bug also hibernate4 4.3.6.1 doesn’t inject the dateCreated, lastUpdated Dates automatically. you have to roll back to 4.3.5.5 and then it works as expected in integration tests

new Grails App : Annoying gripe and time waster : create-drop with default h2 db

September 23, 2014 Leave a comment

fell over this is with latest grails builds GGTS 3.6.1 / grails 2.4.2

if your new to grails what you want to do is quickly add a domain object and try and run some tests quickly etc

instead you get a silly error like this

HHH000389: Unsuccessful: alter table … drop constraint …

and it fails to start. This is frankly annoying and ought to be handled properly – but isn’t fixed yet.

The problem is with in memory DB use and using the create-drop default for hibernate with the H2 drivers. it gets confused as the db doesn’t exist and you can’t drop whats not there .

the easy fix is to override the default H2 dialect. create a file like this in your src/groovy (or java) folders

package com.softwood;

import org.hibernate.dialect.H2Dialect;

/**
 * Workaround.
 * 
 * @see https://hibernate.onjira.com/browse/HHH-7002
 * 
 */
public class ImprovedH2Dialect extends H2Dialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the &quot;if exists&quot; clause to avoid warnings
        return &quot;drop sequence if exists &quot; + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just
        // leads to error messages about missing tables when we don't have a
        // schema in the database
        return false;
    }
}

then in your conf/DataSource.groovy add this line at the top of the file

dataSource.dialect = com.softwood.dialects.ImprovedH2Dialect

then re-run the grails run-app and the problem should disappear

this never used to happen so they ought to provide a fix for it as its very easy to put off new entrants from getting started

alternatively you can set the dbCreate = “update” which avoids the drop call on the empty in memory db

pretty annoying and hope this sames someone some heartache wondering what to do next

Categories: Grails Tags: , ,

Groovy 2 asType conversation

August 13, 2014 Leave a comment

Groovy enables you to provide overload a method “asType (Class clazz)”. However i had some difficulty with this relating to duck typing which didn’t work. Not entirely sure why.

i’d been trying to use a grails app with joda date – LocalDate, and new java8 LocalDate. however the java8 version kept crashing when i ran a test – so i dropped back to java 7 and Joda package.

Hibernate doesn’t seem to handle Joda/Java LocalDates (havn’t tried this very far). So i kept it simple i created a Birthday Domain Class with three int params (year, month,date) and wanted to ensure i could generate a LocalDate from this.

first attempt was try this using duck typing

	Object asType (clazz) {
		if (clazz == LocalDate) {
			new LocalDate (year, month, day)
		}
		else {
			super.asType(clazz)
		}

	}

however this wouldn’t fire when i tried

def bday = new Birthday (year:1962, month:10, day:20) as LocalDate

and it said it couldn’t handle the caste at runtime – odd.

eventually tried and explicitly set the type for the method and then it ran successfully and did the dynamic caste

	Object asType (<strong>Class</strong> clazz) {
		if (clazz == LocalDate) {
			new LocalDate (year, month, day)
		}
		else {
			super.asType(clazz)
		}

	}

adding the explicit type did it

Categories: Grails, Groovy Tags:
%d bloggers like this: