Simplifying dependency management with Grape

Your nicely written and useful script can solve many interesting problems with the help of third-party libraries, and as long as it resides on your machine and has all the dependencies in place, it will work perfectly. However, at the point when you need to share it with your colleagues or community, you will realize that small and concise code requires several megabytes of additional libraries to be passed together with the script in order to make it work. Luckily, Groovy has a solution for that called Grape.

In this recipe, we will show you how to declare and automatically load Groovy script dependencies with the help of the wonderful Grape tool, which is integrated into Groovy.

Getting ready

Grape stands for the Groovy Adaptable (Advanced) Packaging Engine, and it is a part of the Groovy installation. Grape helps you download and cache external dependencies from within your script with a set of simple annotations.

How to do it...

If, in your script, you require an external dependency, that you know is available in a public repository as Maven Central Repository, you can use @Grab annotation to annotate your import, class, or method with a reference to that library, and Groovy will automatically download it, cache it, and put it on the class path of your script:

  1. For example, the search.groovy script is dependent on Apache Commons HttpClient library for making a Google search and saving a result page to a local file:
    @Grab('org.apache.httpcomponents:httpclient:4.2.1')
    import org.apache.http.impl.client.DefaultHttpClient
    import org.apache.http.client.methods.HttpGet
    
    def httpClient = new DefaultHttpClient()
    def url = 'http://www.google.com/search?q=Groovy'
    def httpGet = new HttpGet(url)
    
    def httpResponse = httpClient.execute(httpGet)
    
    new File('result.html').text =httpResponse.entity.content.text
  2. To execute the script, just use the usual invocation: groovy search.groovy mechanism. Groovy will automatically detect any external dependency requirements and tell Grape to fetch it before script execution.

How it works...

The first time the script gets executed, we experience a delay while the dependencies are downloaded. The second time, the script will execute faster because all libraries will be cached in Grape's cache directory, located in .groovygrapes, in the user's home folder. Groovy also provides a command-line tool, grape, to overview and control Grape's library cache. If the Grape's cache was empty in the beginning, then after our script execution, grape's list command will output something as follows:

commons-codec commons-codec  [1.6]
commons-logging commons-logging  [1.1.1]
org.apache apache  [4, 9]
org.apache.commons commons-parent  [22, 5]
org.apache.httpcomponents httpclient  [4.2.1]
org.apache.httpcomponents httpcomponents-client  [4.2.1]
org.apache.httpcomponents httpcomponents-core  [4.2.1]
org.apache.httpcomponents httpcore  [4.2.1]
org.apache.httpcomponents project  [6]
org.ccil.cowan.tagsoup tagsoup  [1.2]

10 Grape modules cached
12 Grape module versions cached

You can put @Grab annotation preceding various elements of the code.

On import:

@Grab('org.apache.httpcomponents:httpclient:4.2.1')
import org.apache.http.impl.client.DefaultHttpClient

def httpClient = new DefaultHttpClient()

On variable:

@Grab('org.apache.httpcomponents:httpclient:4.2.1')
def httpClient =new org.apache.http.impl.client.DefaultHttpClient()

On method:

@Grab('org.apache.httpcomponents:httpclient:4.2.1')
def getHttpClient() {
  new org.apache.http.impl.client.DefaultHttpClient()
}

On class:

@Grab('org.apache.httpcomponents:httpclient:4.2.1')
class Searcher {
  def httpClient
  Searcher() {
    httpClient =
      new org.apache.http.impl.client.DefaultHttpClient()
  }
}

The only rule is that @Grab should appear before the first usage of the imported class; otherwise the Groovy compiler will complain about it.

There's more...

Additionally, the @Grapes annotation can be used to group several dependencies as follows:

@Grapes([
   @Grab('org.apache.httpcomponents:httpclient:4.2.1'),
   @Grab('org.ccil.cowan.tagsoup:tagsoup:1.2')])
class Searcher { ... }

By default, Grape is using the Maven Central Repository (located at http://search.maven.org/) for downloading libraries. If you need to add your own repository, then you can either change grapeConfig.xml, which is in fact, an Apache Ivy configuration, or you can use the @GrabResolver annotation inside the script itself to make it more portable:

@GrabResolver(name='codehaus', root='http://repository.codehaus.org/')
class Searcher { ... }

Like with any dependency management tool, sometimes you need to exclude certain dependencies from a dependency tree, and there, the @GrabExclude annotation comes to the rescue:

@GrabExclude(group='commons-codec',module='commons-codec')
class Searcher { ... }

Under the hood, Grape is using the Apache Ivy library for dependency management and resolution.

If you don't want to wait for the artifact download upon script start, you can use the grape install command to install artifacts before execution:

grape install org.apache.httpcomponents httpclient 4.2.1

You can also use the Grape API directly and prefetch the required dependencies using another Groovy script:

 import groovy.grape.Grape

 Grape.grab(group: 'org.apache.httpcomponents',module: 'httpclient',version: '4.2.1')

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.54.136