Search

Dark theme | Light theme
Showing posts with label GroovyGoodness:Grape. Show all posts
Showing posts with label GroovyGoodness:Grape. Show all posts

September 15, 2015

Groovy Goodness: Exclude Transitive Dependencies With Grape

The built-in dependency mechanism in Groovy is Grape. With Grape we can define dependencies in our code and Groovy will download them and make them available when we run our Groovy application. The easiest way to use it is with the @Grab annotation with a dependency as the value. If we want to exclude a transitive dependency we use the @GrabExclude annotation. We must specify the attributes group and module of the annotation with the dependency we want to exclude. An alternative syntax is a shorthand version where the group and module are combined into a single String value separated by a colon (:).

In the following Groovy script we have a very simple Spring application with Java (Groovy) based configuration. So we need a dependency on the spring-context module. But we don't want to use the standard Spring logging. Spring used Apache Commons logging and we want to replace it with an SLF4J API implementation: Logback. So we use the @GrabExclude annotation to exclude the commons logging dependency. And we add two extra dependencies to replace it: org.slf4j:jcl-over-slf4j and ch.qos.logback:logback-classic.

package com.mrhaki

@Grab('org.springframework:spring-context:4.2.1.RELEASE')
// Exclude the commons-logging dependency 
// as Spring transitive dependency.
@GrabExclude(group = 'commons-logging', module='commons-logging') // Or 'commons-logging:commons-logging'
// Replace commons-logging with SLF4J 
// implementation Logback.
@Grab('org.slf4j:jcl-over-slf4j:1.7.12')
@Grab('ch.qos.logback:logback-classic:1.1.3')
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.AnnotationConfigApplicationContext


// Define Spring Java (Groovy) configuration class.
@Configuration
class AppConfig {

    // Simple bean is a String.
    @Bean
    String obvious() {
        'Groovy is gr8!'
    }
}

// Create new Spring application context and use
// our Groovy configuration class
final ApplicationContext appContext = 
    new AnnotationConfigApplicationContext(AppConfig)

// Check that bean is in application context.
assert appContext.getBean('obvious') == 'Groovy is gr8!'

Written with Groovy 2.4.4.

September 14, 2015

Groovy Goodness: See More Info About Downloading With Grape

Groovy has a advanced feature to define and download dependencies automatically for our code: grape. To get more information about the progress of the dependency resolution and downloading of the dependencies we must use the Java system property groovy.grape.report.downloads and set it to true. Groovy uses Ivy under the hood to handle the dependency management. We can get Ivy logging messages by setting the system property ivy.message.logger.level to a numeric value. The value 4 gives the most logging and value 0 only shows error messages.

In the following example code we use -Dgroovy.grape.report.downloads=true when we invoke a simple Groovy script with a dependency on Apache Commons library:

import org.apache.commons.lang3.SystemUtils
import static org.apache.commons.lang3.JavaVersion.JAVA_1_8 as Java8

@Grab(group='org.apache.commons', module='commons-lang3', version='3.4')
def printInfo() {
    if (SystemUtils.isJavaVersionAtLeast(Java8)) {
        println 'We are ready to use the Stream API in our code.'
    } else {
        println 'We cannot use the Stram API in our code.'
    }
}

printInfo()

Now we run the script with extra logging information:

$ groovy -Dgroovy.grape.report.downloads=true sample.groovy
Resolving dependency: org.apache.commons#commons-lang3;3.4 {default=[default]}
Preparing to download artifact org.apache.commons#commons-lang3;3.4!commons-lang3.jar
Downloaded 424 Kbytes in 414ms:
  [SUCCESSFUL ] org.apache.commons#commons-lang3;3.4!commons-lang3.jar (408ms)
We are ready to use the Stream API in our code.
$ groovy -Dgroovy.grape.report.downloads=true sample.groovy
Resolving dependency: org.apache.commons#commons-lang3;3.4 {default=[default]}
Preparing to download artifact org.apache.commons#commons-lang3;3.4!commons-lang3.jar
We are ready to use the Stream API in our code.

Notice that the second time we run the script the logging shows the JAR file is not downloaded. That is because grape use the downloaded file from the USER_HOME/.groovy/grapes directory.

Written with Groovy 2.4.4.

Groovy Goodness: Change Directory For Saving Dependencies Grape

With Grape in Groovy we can add dependency management for our code. Especially the @Grab annotation is very useful to specify dependencies directly in our code. Groovy will download the dependencies if needed and store them in the USER_HOME/.groovy/grapes directory. If we want to change this directory we must set the Java system property grape.root. We specify the new directory to store the downloaded dependencies as a value.

In the following example we have a simple script with a dependency on the Apache Commons library. We use the -Dgrape.root command line option when we run the script and specify the directory deps. After we have run the script we can see the contents of the deps directory to see the downloaded files.

$ groovy -Dgrape.root=deps/ sample.groovy
$ tree deps
deps
└── grapes
    └── org.apache.commons
        └── commons-lang3
            ├── ivy-3.4.xml
            ├── ivy-3.4.xml.original
            ├── ivydata-3.4.properties
            └── jars
                └── commons-lang3-3.4.jar

4 directories, 4 files

Written with Groovy 2.4.4.

August 25, 2010

Groovy Goodness: Resolve Module Location with Grape

Grape in Groovy is a great way to define dependencies in our scripts and let Groovy download them automatically for us. We also can use the command-line tool grape to resolve the location of modules on our system. We use the resolve command to get the absolute path to our dependency, but we can even pass extra arguments like -shell and -dos and we get the location as a CLASSPATH environment variable. If we use -ant we can use the output in a ANT build file. Or -ivy to get the information in Ivy XML format.

$ grape resolve commons-lang commons-lang 2.5
/Users/mrhaki/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.5.jar

$ grape resolve -dos commons-lang commons-lang 2.5
set CLASSPATH=/Users/mrhaki/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.5.jar

$ grape resolve -shell commons-lang commons-lang 2.5
export CLASSPATH=/Users/mrhaki/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.5.jar

$ grape resolve -ant commons-lang commons-lang 2.5
<pathelement location="/Users/mrhaki/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.5.jar">

$ grape resolve -ivy commons-lang commons-lang 2.5
<dependency org="commons-lang" name="commons-lang" revision="2.4">

May 28, 2010

Groovy Goodness: Use GrabResolver for Custom Repositories

In Groovy we can use the @Grab annotation to define dependencies and automatically download them from public repositories. But maybe we have created our own package and we want to use it in our Groovy script. Our own package is deployed to a customer Maven 2 compatible repository with the url http://customserver/repo, so it is not available to the general public. We can use @GrabResolver to add this repository as a source to look for dependencies in our script. In the following sample code we assume the module groovy-samples, version 1.0 is deployed in the repository accessible via http://customserver/repo:

@GrabResolver(name='custom', root='http://customserver/repo', m2Compatible='true')
@Grab('com.mrhaki:groovy-samples:1.0')
import com.mrhaki.groovy.Sample

def s = new Sample()
s.justToShowGrabResolver()  // Just a sample