openlogic
DESCRIPTION
TRANSCRIPT
Groovy = Java + Ruby + Pythonfor the JVM
Rod Cope
26/22/2005
Groovy Goals
• Learn what Groovy can do for you• Start using it today!
36/22/2005
Rod Cope• Founder and CTO of OpenLogic
• 9+ years Java experience– Sun Certified Java Architect– J2SE, J2EE, J2ME, Swing, Security, Open Source, etc.– GE, IBM, Ericsson, Manugistics, Digital Thoughts, etc.
• Groovy Lover– Started November 2003– 7,000+ lines of Groovy in production (small apps)– Groovy Presentations
• No Fluff Just Stuff Series• JavaOne• O'Reilly Open Source Convention
46/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
56/22/2005
Agenda
• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
66/22/2005
Sample: Javapublic class Filter {public static void main( String[] args ) {
List list = new ArrayList();list.add( "Rod" ); list.add( "Neeta" );list.add( "Eric" ); list.add( "Missy" );
Filter filter = new Filter();List shorts = filter.filterLongerThan( list, 4 );System.out.println( shorts.size() );
Iterator iter = shorts.iterator();while ( iter.hasNext() ) {System.out.println( iter.next() );
}}public List filterLongerThan( List list, int length ) {
List result = new ArrayList();Iterator iter = list.iterator();while ( iter.hasNext() ) {String item = (String) iter.next();if ( item.length() <= length ) { result.add( item ); }
}return result;
}}
and Groovy!
76/22/2005
Sample: Groovy!
def list = ["Rod", "Neeta", "Eric", "Missy"]def shorts = list.findAll { it.size() <= 4 }println shorts.size()shorts.each { println it }
groovy> 2groovy> Rod
Eric
86/22/2005
Sample in Java (27 lines)public class Filter {public static void main( String[] args ) {
List list = new ArrayList();list.add( "Rod" ); list.add( "Neeta" );list.add( "Eric" ); list.add( "Missy" );
Filter filter = new Filter();List shorts = filter.filterLongerThan( list, 4 );System.out.println( shorts.size() );
Iterator iter = shorts.iterator();while ( iter.hasNext() ) {System.out.println( iter.next() );
}}public List filterLongerThan( List list, int length ) {
List result = new ArrayList();Iterator iter = list.iterator();while ( iter.hasNext() ) {String item = (String) iter.next();if ( item.length() <= length ) { result.add( item ); }
}return result;
}}
96/22/2005
Sample in Groovy (4 lines)
def list = ["Rod", "Neeta", "Eric", "Missy"]def shorts = list.findAll { it.size() <= 4 }println shorts.size()shorts.each { println it }
106/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
116/22/2005
Java Platform Strengths• Lots of reusable software, components, tools• VM and Binary Compatibility
– Build deployment units (class, jar, jnlp, war, ear, sar, etc.) and run them anywhere
– Easily reuse libraries and tools
• Allows for innovation at the source code level
126/22/2005
Components vs. Scripting• We reuse far more code than we write • We spend more time gluing components than writing them• We write more tests than real code• The web tier is a perfect example
– Render business objects as markup (templating / scripting)– Glue actions with requests and domain models (MVC)– Most of web tier is duct tape with pockets of business logic
• Scripting is a great way to glue components together
136/22/2005
Why Another Agile Language?• Want complete binary compatibility with Java
– No difference from Java at JVM / bytecode level– No wrappers or separate islands of APIs
• Java-friendly syntax– Don't want something totally foreign to Java developers
• Want a scripting language designed:– for the Java Platform– by Java developers– for Java developers
146/22/2005
Groovy
• Who/When– James Strachan, Bob McWhirter – August 2003
• What– Dynamic, object-oriented scripting language for JVM– Features of Ruby, Python, and Smalltalk
• Why– J/Python, J/Ruby, BeanShell, etc. all lacking
• How– Initially, hand-written compiler and bytecode generator– Now uses ANTLR and ASM
156/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
166/22/2005
Groovy Features• Dynamic and Static Typing
def str = "Hello"int a = 2
• Native syntax for lists, maps, arrays, beans, etc.def list = ["Rod", 3, new Date()]def myMap = ["Neeta":31, "Eric":34]
• ClosuresmyMap.each(
{ name, age -> println "$name is $age years old" } )groovy> Eric is 34 years oldgroovy> Neeta is 31 years old
176/22/2005
Groovy Features (cont.)• Regex built-in
if ( "name" ==~ "na.*" ) { println "match!" }groovy> match!
• Operator overloadingdef list = [1, 2, 3] + [4, 5, 6]list.flatten().each { print it }
groovy> 123456
• Autoboxing and polymorphism across collection, array, map, bean, String, iterators, etc.String[] array = ['cat', 'dog', 'mouse']def str = 'hello'println "${array.size()},${str.size()},${list.size()}"
groovy> 3,5,6
186/22/2005
Groovy JDK• Groovy-er JDK: adds convenient methods to JDK• String
– contains(), count(), execute(), padLeft(), center(), padRight(), reverse(), tokenize(), each(), etc.
• Collection– count(), collect(), join(), each(), reverseEach(), find/All(), min(), max(), inject(), sort(), etc.
• File– eachFile(), eachLine(), withPrintWriter(), write(), getText(), etc.
• Lots there and growing all the time• You can add methods programmatically
196/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
206/22/2005
Working with Java• Create Adder.java
package com.openlogic.test;public interface Adder{
public int add( int a, int b );}
• Create GAdder.groovypackage com.openlogic.testclass GAdder implements Adder{
public int add( int a, int b ){
return a + b}
}
216/22/2005
Working with Java (cont.)• Compile the Java code
javac -d target Adder.java
• Compile the Groovy codegroovyc --classpath target GAdder.groovy
• Use the Groovy code inside Java with the interfaceAdder adder = new com.openlogic.test.GAdder();int answer = adder.add( 1, 2 );System.out.println( "Answer = " + answer );groovy> Answer = 3
226/22/2005
Working with Ant
• BSF-compliant<script language="groovy">println 'hi' * 2</script>
• Groovy task<taskdef name="groovy"
classname="org.codehaus.groovy.ant.Groovy" classpath="groovy-all-1.0-jsr-2.jar"/>
<groovy>def x = 2for ( count in 1..x ) {
ant.echo( "hello world ($count)" )}ant.jar( destfile: "c:/stuff.jar", basedir: "." )
</groovy>
236/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
246/22/2005
Groovy Markup• Native support for hierarchical structures in
code– XML– XHTML– Ant– Swing– SWT
• Relatively easy to add your own
256/22/2005
Groovy Markup: XML<people>
<person name='Rod'><pet name='Bowie' age='3' /><pet name='Misha' age='9' />
</person><person name='Eric'>
<pet name='Poe' age='5' /><pet name='Doc' age='4' />
</person></people>
266/22/2005
Groovy Markup: XML (cont.)
data = ['Rod': ['Misha':9, 'Bowie':3],'Eric': ['Poe':5, 'Doc':4] ]
xml = new groovy.xml.MarkupBuilder()
doc = xml.people() {for ( entry in data ) {person( name: entry.key ) {for ( dog in entry.value ) {pet( name:dog.key, age:dog.value )
}}
}}
276/22/2005
Groovy Markup: XML Parsingxml = """<people><person name="Rod">
<pet name="Misha" age="9"/><pet name="Bowie" age="3"/>
</person><person name="Eric">
<pet name="Poe" age="5"/><pet name="Doc" age="4"/>
</person></people>"""
people = new groovy.util.XmlParser().parseText( xml )println people.person.pet['@name']
groovy> ['Misha','Bowie','Poe','Doc']
286/22/2005
XML: Transformation• Advanced XML Generation
– StreamingMarkupBuilder in sandbox generates HTML and complex XML - used to generate GDK javadoc
• Groovy as Human-Readable XSLT– Use XML parsing and navigation (findAll, every, any, etc.) to
locate data– Use MarkupBuilder, StreamingMarkupBuilder, etc. to
render new format– Example in groovy.util.NavToWiki.groovy -
transforms XDoc to Wiki
296/22/2005
XML: Transformation Example• In navigation.xml:
<body><links><item name="Download" href="download.html"/><item name="JavaDoc" href="apidocs/index.html"/> ...
• Excerpt from groovy.util.NavToWiki.groovydoc = new XmlParser().parse("navigation.xml")
items = doc.body.links.itemprintln items.collect { item ->
"{link:${item['@name']}|${item['@href']}}"}.join(" | ")
-> {link:Download|download.html} | {link:JavaDoc|apidocs/index.html}
306/22/2005
Groovy Markup: Antant = new groovy.util.AntBuilder()
ant.echo( 'starting...' )ant.sequential {
def mydir = 'c:/backups'mkdir( dir: mydir )copy( todir: mydir ) {
fileset( dir: 'src/test' ) {includes( name:'**/*.groovy' )
}}echo( "done!" )
}
316/22/2005
Groovy Markup: Swingdef swing = new groovy.swing.SwingBuilder() frame = swing.frame(title: 'My Frame', size: [800,400]) {
menuBar {menu(text: 'File') {
menuItem() {action(name:'New', closure:{ println("New") })
}}
}panel(layout:new BorderLayout()) {
label(text: 'Name', constraints: BorderLayout.WEST,toolTipText: 'This is the name field')
button(text: 'Click me!',constraints: BorderLayout.SOUTH,actionPerformed: { println("Click!") } )
}} frame.show()
326/22/2005
Groovy SQLsql = new groovy.sql.Sql( dataSource )sql.execute( "create table person
( name varchar, age integer)" )
people = sql.dataSet( "person" )people.add( name: "Rod", age: 34 )people.add( name: "Neeta", age: 31 )
sql.eachRow( "select * from person" ) { p ->println "$p.name is $p.age years old"
}
groovy> Rod is 34 years oldgroovy> Neeta is 31 years old
336/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
346/22/2005
Extras
• Processes: "cmd /c dir".execute().text• Threading: Thread.start { any code }• Testing: GroovyTestCase, GroovyMock• SWT: Full support for SWT building, like SwingBuilder• Groovy Pages/Template Engine: GSP, Groovlets, etc.• Thicky: Groovy-based fat client delivery via GSP• Unix Scripting: Groovy API for pipe, cat, grep, etc.• Eclipse, IntelliJ, JEdit: Groovy plug-ins available• Native Compiler for Linux/Intel: Very early – maybe
dead• JMX: Small sample available• ActiveX Proxy: Control over MS Windows (IE, Excel,
etc.)
356/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
366/22/2005
Demo: XML-RPC
• XML-based Communication (like SOAP)• Server and Client side support• Separate Module in Groovy (not in core)
376/22/2005
XML-RPC– import groovy.net.xmlrpc.*
– Serverserver = new XMLRPCServer()server.testme = { | name | name + " is cool!" }server.multiply = { | number | number * 10 }serverSocket = new java.net.ServerSocket( 9047 )server.startServer( serverSocket )
– ClientserverProxy=new XMLRPCServerProxy("http://127.0.0.1:9047")println serverProxy.testme( "Groovy" ) -> "Groovy is cool!"println serverProxy.multiply( 7 ) -> 70server.stopServer()
386/22/2005
Demo: Groovy Automation
• ActiveXProxy• Easy native Windows access through Groovy• Uses Jacob Library (danadler.com/jacob)
396/22/2005
ActiveXProxy: Internet Explorerimport org.codehaus.groovy.scriptom.ActiveXProxyexplorer = new ActiveXProxy("InternetExplorer.Application")
explorer.Visible = trueexplorer.AddressBar = trueexplorer.Navigate("http://www.openlogic.com")explorer.StatusText = "OpenLogic home page"explorer.events.OnQuit = { println "Quit" }explorer.events.listen()Thread.sleep(3000)explorer.Quit()
406/22/2005
ActiveXProxy: Excelimport org.codehaus.groovy.scriptom.ActiveXProxyexcel = new ActiveXProxy("Excel.Application")excel.Visible = trueThread.sleep(1000)workbooks = excel.Workbooksworkbook = workbooks.Add()sheet = workbook.ActiveSheeta1 = sheet.Range('A1')a2 = sheet.Range('A2')a1.Value = 125.3a2.Formula = '=A1 * 2'println "a2: ${a2.Value.value}"
groovy> 250.6Workbook.close( false, null, false )excel.Quit()
416/22/2005
Agenda• Groovy Sample• Genesis of Groovy• Groovy Features• Working with Java• Groovy Markup• Extras• Demo• Conclusion
426/22/2005
Trouble in Paradise• Weak and Missing Features
– No support for inner classes– Tool support (Eclipse, IntelliJ, etc.) not great, getting better
• Debugging/Scripting Hell– Immature parser: hard to find "real" bugs– Lots of rope: easy to hang yourself with dynamic code
• Language Instability– Lots of syntactic sugar: nice to have, but may change– Java camp vs. non-Java camp: competing directions– "JSR Groovy" versus "Old Groovy"
436/22/2005
Conclusion• Status
• 1.0 release expected later this summer• Development Time
– Less than half that of Java• Performance
– 20-90% of Java, depending on usage– Very little tuning so far, waiting for 1.0 release
• Recommendations– Ready for small, non-mission-critical projects– Try it! Very easy to learn and lots of fun!
446/22/2005
For More Information• Groovy Home Page
– http://groovy.codehaus.org
• GDK Javadoc– http://groovy.codehaus.org/groovy-jdk.html
• JSR-241: The Groovy Programming Language– http://www.jcp.org/en/jsr/detail?id=241
• James Strachan's Blog– http://radio.weblogs.com/0112098/
456/22/2005
Q&A Period
Any questions?