Posts Tagged ‘Groovy’
[DevoxxBE2013] Part 1: Thinking Functional Style
Venkat Subramaniam, an award-winning author and founder of Agile Developer, Inc., guides developers through the paradigm shift of functional programming on the JVM. Renowned for Functional Programming in Java and his global mentorship, Venkat uses Java 8, Groovy, and Scala to illustrate functional tenets. His session contrasts imperative statements with composable expressions, demonstrating how to leverage lambda expressions and higher-order functions for elegant, maintainable code.
Functional programming, Venkat posits, transcends syntax—it’s a mindset fostering immutability and data flow. Through practical examples, he showcases Groovy’s idiomatic functional constructs and Scala’s expression-driven purity, equipping attendees to rethink application design.
Functional Principles and Expressions
Venkat contrasts statements—imperative, mutation-driven blocks—with expressions, which compute and return values. He demos a Java 8 stream pipeline, transforming data without side effects, versus a loop’s mutability.
Expressions, Venkat emphasizes, enable seamless composition, fostering cleaner, more predictable codebases.
Groovy’s Functional Idioms
Groovy, though not purely functional, excels in functional style, Venkat illustrates. He showcases collect and findAll for list transformations, akin to Java 8 streams, with concise closures.
These idioms, he notes, simplify data processing, making functional patterns intuitive for Java developers.
Scala’s Expression-Driven Design
Scala’s expression-centric nature shines in Venkat’s examples: every construct returns a value, enabling chaining. He demos pattern matching and for-comprehensions, streamlining complex workflows.
This purity, Venkat argues, minimizes state bugs, aligning with functional ideals.
Higher-Order Functions and Composition
Venkat explores higher-order functions, passing lambdas as arguments. A Groovy example composes functions to filter and map data, while Scala’s currying simplifies partial application.
Such techniques, he asserts, enhance modularity, enabling parallelization for performance-critical tasks.
Practical Adoption and Parallelization
Venkat advocates starting with small functional refactors, like replacing loops with streams. He demos parallel stream processing in Java 8, leveraging multi-core CPUs.
This pragmatic approach, he concludes, bridges imperative habits with functional elegance, boosting scalability.
Links:
[DevoxxFR2013] Groovy and Statically Typed DSLs
Lecturer
Guillaume Laforge manages the Groovy project and leads JSR-241 for its standardization. As Vice President of Technology at G2One, he delivers services around Groovy/Grails. Co-author of “Groovy in Action,” he evangelizes at global conferences.
Cédric Champeau contributes to Groovy core at SpringSource (VMware division). Previously at Lingway, he applied Groovy industrially in DSLs, scripting, workflows.
Abstract
Guillaume Laforge and Cédric Champeau explore Groovy’s evolution in crafting statically typed domain-specific languages (DSLs). Building on runtime metaprogramming, Groovy 2.1 introduces compile-time features for type safety without sacrificing flexibility. They demonstrate extensions, AST transformations, and error reporting, culminating in advanced builders surpassing Java’s checks, illustrating implications for robust, expressive DSL design.
Groovy’s DSL Heritage: Dynamic Foundations and Metaprogramming
Laforge recaps Groovy’s DSL prowess: flexible syntax, runtime interception (invokeMethod, getProperty), closures for blocks.
Examples: method missing for fluent APIs, expando meta-classes for adaptations.
This dynamism accelerates development but risks runtime errors. Groovy 2 adds optional static typing (@TypeChecked), clashing initially with dynamic DSLs.
Bridging Static and Dynamic: Compile-Time Extensions
Champeau introduces Groovy 2.1’s static compile-time metaprogramming. @CompileStatic enables type checking; extensions handle DSL specifics.
Trait-like extensions via extension modules: add methods to classes statically.
// Extension class
class HtmlExtension {
static NodeBuilder div(Element self, Closure c) { /* build */ }
}
Register in META-INF, usable in typed code with error propagation.
This preserves DSL fluency under static compilation.
AST Transformations for Deeper Integration
Custom AST transformations inject code during compilation. @Builder variants, delegation.
For DSLs: transform method calls into builders, validate arguments statically.
Example: markup builder with type-checked HTML generation, reporting mismatches at compile-time.
Champeau details global transformations for cross-cutting concerns.
Advanced Type Checking: Custom Error Reporting and Beyond Java
Laforge showcases @TypeChecked with custom type checkers. Override doVisit for context-specific rules.
@TypeChecked
void script() {
html {
div(id: 'main') { /* content */ }
}
}
Checker ensures div accepts valid attributes, closures; errors reference user code lines.
Groovy exceeds Java: infer types in dynamic contexts, enforce domain rules unavailable in Java.
Builder Patterns and Real-World Applications
Demonstrate HTML DSL: nested closures build node trees, statically verified.
Grails integration: apply to GSPs for compile-time validation.
Champeau notes Grails’ metaprogramming complexity as ideal testbed—getProperty, MOP, AST all in play.
Implications for DSL Engineering: Safety, Productivity, Evolution
Static typing catches errors early, aids IDE support (autocompletion, refactoring). Dynamic essence retained via extensions.
Trade-offs: setup complexity; mitigated by community modules.
Future: deeper Grails incorporation, enhanced tooling.
Laforge and Champeau position Groovy as premier for type-safe yet expressive DSLs, blending agility with reliability.
Links:
How to compile both Java classes and Groovy scripts with Maven?
Case
Your project includes both Java classes and Groovy scripts. You would like to build all of them at the same time with Maven: this must be possible, because, after all, Groovy scripts are run on a Java Virtual Machine.
Solution
In your pom.xml, configure the maven-compiler-plugin as follows:
[xml] <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<source>1.6</source>
<target>1.6</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.8.0-01</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.1.5-03</version>
</dependency>
</dependencies>
</plugin>[/xml]
With such setup, default compiler (which cannot compile Groovy scripts parallelly of Java sources) will be replaced with Eclipse’s one (which can).
(long tweet) Error injecting: org.codehaus.groovy.eclipse.compiler.GroovyEclipseCompiler
Case
On building a Groovy project with Maven, I got the following error:
[java]Error injecting: org.codehaus.groovy.eclipse.compiler.GroovyEclipseCompiler
java.lang.NoClassDefFoundError: org/codehaus/plexus/compiler/CompilerResult[/java]
Quick fix
Downgrade maven-compiler-plugin to version 3.0 instead of branch 2.3.X.
How to call external shell in Groovy?
Going on learning Groovy, I faced the following case: how to call an external shell (or MS-DOS) command from a Groovy script?
It is very easy. The following example show how to display the Subversion status of the current folder:
[java]def proc = "svn st"
def sb = new StringBuffer()
proc.consumeProcessErrorStream(sb)
println proc.text + "\n" + sb.toString()
[/java]
Error grabbing Grapes — [unresolved dependency: com.oracle#ojdbc14;10.2.0.4.0: not found]
I have learnt Groovy since the beginning of the week.
I had to import some classes from Oracle JDBC driver. As a newbie, I wrote the following annotation:
[java]@Grab(group = ‘com.oracle’, module = ‘ojdbc14’, version = ‘10.2.0.4.0’)[/java]
I got the following error:
[java]Error grabbing Grapes — [unresolved dependency: com.oracle#ojdbc14;10.2.0.4.0: not found][/java]
To sum up, adding a dependency to Oracle driver raises two issues:
- adding any external dependency
- adding a dependency to any JDBC driver
Indeed, Grab requires a kind of Maven repository, and you can catch the link between the @Grab annotation below and classic Maven 2 <dependency> tag. As I understood, Grab instructions are closer to Ivy than to Maven system. In my situation, having no “Grab repo” (I don’t know how to call that), I had to download the jars from a Maven repo. To fix it, two operations are needed: hint at Maven (or Ivy) repo, and allow Groovy to access the network.
Regarding the second issue, it is answered by added a @GrabConfig annotation.
Therefore, to fix the original issue:
-
replace [java]@Grab(group = ‘com.oracle’, module = ‘ojdbc14’, version = ‘10.2.0.4.0’)[/java]
with[java]@GrabConfig(systemClassLoader=true)
@GrabResolver(name=’nameOfYourMavenRepo, root=’http://url-of-your-maven-repo:port’)
@Grab(group = ‘com.oracle’, module = ‘ojdbc14’, version = ‘10.2.0.4.0’)
[/java] - at first run, if needed, hint at the proxy to allow Grab to download the Jars, eg: [java]groovy -Dhttp.proxyHost=myProxyHost -Dhttp.proxyPort=8080[/java]
You may notice the needed JAR will be written in the $USER_HOME/.groovy/grapes folder.
Filter too large files in Mule ESB
Case
You use a filter connector in Mule ESB 2.2.1, to perform any operation (let’s say: to send them on JMS, but this does not matter). You would like to filter files owing to their size, ie stop the handling of files larger than 10,000,000 bytes for instance.
We assume the files you handle are text files (not binary).
Solution
In your Mule XML config file, add the following block, using a short Groovy script:
[xml]<message-properties-transformer name="add-properties">
<add-message-property key="fileSizeOK"
value="#[groovy:message.getPayload().size() < 10000000]" />
</message-properties-transformer>[/xml]
In the tag <file:inbound-endpoint>, add the attribute: transformer-refs="add-properties"
Now, add a tag <message-property-filter pattern="fileSizeOK=true"/>. Your outbound should then be similar to:[xml] <outbound>
<filtering-router>
<jms:outbound-endpoint queue="lalou.jonathan.jms.queue"
connector-ref="jmsConnector"/>
<message-property-filter pattern="fileSizeOK=true"/>
</filtering-router>
<forwarding-catch-all-strategy>
<file:outbound-endpoint path="/my/folder/"
connector-ref="fileConnector" outputPattern="error/#[header:originalFilename].too_big.#[function:dateStamp:yyyyMMdd_HHmmss_SSSSS].KO" />
</forwarding-catch-all-strategy>
</outbound>[/xml]
Many thanks to Vincent N. for his help.
Could not initialize class net.sf.cglib.proxy.Enhancer
Error
Compiling with Maven 2, you have:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [businessApplicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.proxy.Enhancer
Caused by: java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.proxy.Enhancer
Turning Spring logging level to DEBUG, you find:
DEBUG main org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver - Ignoring handler [org.springframework.scripting.config.LangNamespaceHandler]: problem with class file or dependent class
java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException
Fix
Add dependencies to Groovy, BSH and JRuby in your pom.xml:
[xml]
<dependency>
<groupId>groovy</groupId>
<artifactId>groovy</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.beanshell</groupId>
<artifactId>bsh</artifactId>
<version>2.0b4</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>0.9.8</version>
</dependency>
[/xml]
Try of Explanation
Spring depends on the three jars above. But Maven does not link your project to them.