a tour through the groovy ecosystem

Post on 06-May-2015

1.854 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Groovy presentation from Dyncon 2011 in Sweden

TRANSCRIPT

Leonard Axelsson

• Groovy developer since 2007• Co-Founder of SweGUG

–Swedish Groovy User Group• Speaker at Javaforum,

GTUG, Agical Geeknight, JFokus, SweGUG

• Developer/Consultant at Agical

@xlsonhttp://xlson.com/

Saturday, March 12, 2011

a long long time ago (4 years or so ;)

Saturday, March 12, 2011

Overview

• Part 1: Groovy intro ~15 mins

• Short and sweet

• Part 2: Ecosystem ~20 mins

• Mapping the wilderness

• Part 3: Questions?!?!? :)

Saturday, March 12, 2011

Groovy Overview

• Originated in 2003

• Under the Apache License

• Runs on the Java Virtual Machine

• Grammar derived from Java 1.5

Saturday, March 12, 2011

Groovy Overview• Dynamic language

• Inspired by Python, Ruby and Smalltalk

• Object Oriented

• Easy to learn for Java devs

• Supports Java style code out of the box

• Scriptable

• Embeddable

Saturday, March 12, 2011

Dynamic Language• No compile-time checking

• int i = “Hello” throws exception at runtime

• Ducktyping

• def keyword allows you to care about what the object does, not what it is

• Supports custom DSLsnew DateDSL().last.day.in.december( 2009 )

http://groovyconsole.appspot.com/view.groovy?id=27001

Saturday, March 12, 2011

The obligatory Hello World

Saturday, March 12, 2011

How many in here know Groovy?

Saturday, March 12, 2011

Ok, so how many in here know some Java?

Saturday, March 12, 2011

class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); }}

HelloWorld.java

Saturday, March 12, 2011

class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); }}

HelloWorld.groovy

Saturday, March 12, 2011

class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); }}

Removing ...

Saturday, March 12, 2011

class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!") }}

Removing ...

Saturday, March 12, 2011

class HelloWorld { public static void main(String[] args) { println("Hello World!") }}

Removing ...

Saturday, March 12, 2011

println("Hello World!")

Removing ...

Saturday, March 12, 2011

println "Hello World!"

This is it

Saturday, March 12, 2011

Feature Overview• Properties

• dynamic getters and setters

• Closures

• reusable blocks of code

• Meta Object Protocol

• rewrite behaviour at runtime

• Many additions to the JDK

Saturday, March 12, 2011

Primitives are objects to// Normal stringString message = 'got $5?'

// Double quoted string supports macrosString longerMessage = "Have you $message"

// Multiline strings available as wellString email = """Hi!How are you?

/Leo"""

println messageprintln longerMessageprintln email

int a = 5long b = 1float f = 5.4double d = 5.4

Saturday, March 12, 2011

Plain Old Groovy Objects

Saturday, March 12, 2011

POGO’s

• Properties

• getters and setters are created automatically

Saturday, March 12, 2011

POGO’s

• Properties

• getters and setters are created automatically

• Named Parameters

• clarifies intent

Saturday, March 12, 2011

POGO’s

class Person { String name String lastname}

def anders = new Person(name: 'Anders', lastname: 'Andersson')assert anders.getName() == 'Anders'

// Anders gets married and changes his lastnameanders.setLastname("Sundstedt")assert anders.lastname == "Sundstedt"

Saturday, March 12, 2011

POGO’s• Getters and setters can be overridden

class Person { def name def lastname String setLastname(String lastname) { this.lastname = lastname.reverse() }}

def anders = new Person(name: 'Anders', lastname: 'Andersson')

// Anders does a strange change of his lastnameanders.lastname = "Sundstedt"assert anders.lastname == "tdetsdnuS"

Saturday, March 12, 2011

Built in syntax for lists and maps

Saturday, March 12, 2011

Lists

def names = ['Leonard', 'Anna', 'Anders']assert names instanceof Listassert names.size() == 3assert names[0] == 'Leonard'

List syntax:

Saturday, March 12, 2011

Mapsdef map = [name: 'Leonard', lastname: 'Axelsson']assert map.name == 'Leonard'assert map['lastname'] == 'Axelsson'

map.each{ key, value -> println "Key: $key, Value: $value"}

Key: name, Value: LeonardKey: lastname, Value: Axelsson

Output:

Saturday, March 12, 2011

each, find and findAllclass Person { String name String lastname boolean male}

def ages = [new Person(name: 'Bo', lastname: 'Olsson', male: true), new Person(name: 'Gunn', lastname: 'Bertilsson', male: false), new Person(name: 'Britt', lastname: 'Olsson', male: false)]// Print all namesages.each { println "$it.name $it.lastname" }

// Find one maleassert ages.find{ person -> person.male }.name == 'Bo'

// or find all females assert ages.findAll{ Person p -> !p.male }.size() == 2

Saturday, March 12, 2011

Putting the basics together

(0..7).collect{(('a'..'z')+('A'..'Z')+(0..9))[new Random().nextInt(62)]}.join()

Saturday, March 12, 2011

AST TransformationsCompile-time meta programming

Saturday, March 12, 2011

@Log

import groovy.util.logging.*

@Logclass LogDemo { def usesLogger() { log.info "Uses the log annotation." } static void main(String[] args) { new LogDemo().usesLogger() }}

Saturday, March 12, 2011

@Immutableimport groovy.transform.*

@Immutableclass User { String name String lastname}

def user = new User(name: 'Leo', lastname: 'Axelsson')

try { user.name = 'Anders'} catch(ReadOnlyPropertyException e) { println("Changing a property of an Immutable object will not work.")}

println user

Saturday, March 12, 2011

@EqualsAndHashCode

import groovy.transform.*

@EqualsAndHashCodeclass User { String name String lastname}

def user1 = new User(name: 'Leo', lastname: 'Axelsson')def user2 = new User(name: 'Leo', lastname: 'Axelsson')

assert user1 == user2

Saturday, March 12, 2011

Mapping the ecosystem

So, we’ve already started, but let’s do some more sightseeing...

Saturday, March 12, 2011

GPars• Parallelization framework

• Features

• Actors

• Agents

• Dataflow

• Parallell Collection Processing

Saturday, March 12, 2011

@Grab(group='org.codehaus.gpars', module='gpars', version='0.10')import groovyx.gpars.GParsExecutorsPool

def importProcessingData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ,18, 19, 20]

time('Parallel execution') { GParsExecutorsPool.withPool { importProcessingData.eachParallel { data -> // Insert arbitrary heavy operation here sleep 200 } }}

time('Linear execution') { importProcessingData.each { // Insert arbitrary heavy operation here sleep 200 }}

def time(String desc, task) { def startTime = new Date().time def result = task() def executionTime = new Date().time - startTime println "$desc took: $executionTime ms." result}

GPars

Saturday, March 12, 2011

GPars• Output (executed on dual-core machine):Parallel execution took: 1449 ms.Linear execution took: 4006 ms.

Saturday, March 12, 2011

@Grab and grape• Dependency management using Apache Ivy

• Uses Maven Central

• grape

• Commandline tool to manage dependencies

• @Grab annotation

• Provides dependcies in scripts

Saturday, March 12, 2011

Web

Saturday, March 12, 2011

Grails

• Convention Over Configuration

• Used on one of Great Britains biggest(?) public sites: Sky.com

• Stands upon the shoulders of giants

• Rich plugin system

Saturday, March 12, 2011

Grails

• Convention Over Configuration

• Used on one of Great Britains biggest(?) public sites: Sky.com

• Stands upon the shoulders of giants

• Rich plugin system

More about Grails tomorrow at 13:40-14:20

with Henk Jurriens! :)

Saturday, March 12, 2011

Testing,what to say about testing...• Spock

• EasyB

• GroovyTestCase

• MockFor()

• Expandos and Maps

• Geb

• SoapUI

• Groovy Remote Control

Saturday, March 12, 2011

Spock

• Great testing framework

• Easy to read (and write)

Saturday, March 12, 2011

Spock:Readable tests

@Grab('org.spockframework:spock-core:0.5-groovy-1.8')@GrabExclude('org.codehaus.groovy:groovy-all:1.8.0-beta-3')import spock.lang.*

class ReadableSpec extends Specification { def "All is well in math-land"() { expect: sum == a + b where: a | b | sum 1 | 5 | 6 6 | 2 | 8 }}

Saturday, March 12, 2011

Spock:Unroll your tests

@Grab('org.spockframework:spock-core:0.5-groovy-1.8')@GrabExclude('org.codehaus.groovy:groovy-all:1.8.0-beta-3')import spock.lang.*

class UnrolledSpec extends Specification { @Unroll({"The sum of $a and $b should be $sum."}) def "All is well in math-land"() { expect: sum == a + b where: a | b | sum 1 | 5 | 6 6 | 2 | 8 10 | 2 | 11 }}

Saturday, March 12, 2011

Geb• Wanna surf programmatically?

• Geb == really nice and easy browser automation

• jQuery style for navigation API

• even supports calling out to jQuery

• Page objects

Saturday, March 12, 2011

Geb:Headless Browsing

@Grab('org.codehaus.geb:geb-core:0.5.1')@Grab('org.seleniumhq.selenium:selenium-htmlunit-driver:2.0a7')import geb.Browser Browser.drive("http://xlson.com/") { assert title == "Leonard Axelsson"}

Saturday, March 12, 2011

Geb:Finding Dyncon using Firefox@Grab('org.codehaus.geb:geb-core:0.5.1')@Grab('org.seleniumhq.selenium:selenium-firefox-driver:2.0a7')import geb.Browser Browser.drive("http://google.se/") { assert title == 'Google' $("input", name: "q").value("Dyncon 2011") $("input", name: "btnG").click()

waitFor { title.startsWith("Dyncon 2011") }

def firstLink = $("li.g", 0).find("a.l") assert firstLink.text() == "Dyncon 2011" firstLink.click()}

Saturday, March 12, 2011

Building

Saturday, March 12, 2011

AntBuilder

• Gives you the power of Ant in Groovy

• ..the power of what?

• Well, platform independent file handling among other things

Saturday, March 12, 2011

AntBuilderdef ant = new AntBuilder()

// lets just call one taskant.echo("hello")

// here is an example of a block of Ant inside GroovyMarkupant.sequential { echo("inside sequential") myDir = "target/AntTest/" mkdir(dir:myDir) copy(todir:myDir) { fileset(dir:"src/test") { include(name:"**/*.groovy") } } echo("done")}

// now lets do some normal Groovy againfile = new File("target/AntTest/groovy/util/AntTest.groovy")assert file.exists()

Saturday, March 12, 2011

Gradle• Easy to get started with

• Bye bye ‘copy-paste’-pattern

• Declarative OR Build by Convention

• Extremely Extendable

• Integrates with Ivy for dependency management

Saturday, March 12, 2011

Gradle:Highlights

• Easy for the first 80% of functionality

• ...easy for the 20% last as well

• Keeps track of what’s changed

• Works everywhere thanks to the Gradle Wrapper

Saturday, March 12, 2011

Gradle:Simply Groovy

apply plugin: 'groovy'apply plugin: 'application'

repositories { mavenCentral()}

dependencies { groovy 'org.codehaus.groovy:groovy-all:1.7.9'}

mainClassName='HelloWorld'

Saturday, March 12, 2011

Gradle:Multiproject

• Head out to the code... :)

Saturday, March 12, 2011

Other goodies

Saturday, March 12, 2011

Griffon

• Grails for the desktop

• Early days but lots of plugins

• DSL for Swing

• Extends SwingBuilder

Saturday, March 12, 2011

GroovyServ

• Speeds up execution of Groovy scripts

• Groovy for small utils finally valid!

Saturday, March 12, 2011

GroovyServ:Pretty XML on the commandline

#!/usr/bin/env groovyclient

println(prettyPrintXml(System.in.text))

def prettyPrintXml(text) { def xmlNode = new XmlParser().parseText(text) def writer = new StringWriter() def printer = new XmlNodePrinter(new PrintWriter(writer)) printer.preserveWhitespace = true printer.print(xmlNode) writer.toString().trim()}

Saturday, March 12, 2011

Links• Groovy

• http://groovy.codehaus.org/

• Groovy Goodness (great tips and trix)

• http://mrhaki.blogspot.com/

• Groovy Web Console (on Appengine)

• http://groovyconsole.appspot.com/

• My blog

• http://xlson.com/

• SweGUG

• http://groups.google.com/group/swegug

Saturday, March 12, 2011

top related