官术网_书友最值得收藏!

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 .groovy\grapes, 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

主站蜘蛛池模板: 乃东县| 贵阳市| 自贡市| 保山市| 法库县| 龙陵县| 柞水县| 北辰区| 富阳市| 和顺县| 静安区| 庆元县| 沧州市| 晋城| 奈曼旗| 固阳县| 新竹市| 子洲县| 延安市| 龙州县| 永州市| 富裕县| 大英县| 平舆县| 大新县| 新安县| 南涧| 修文县| 新乡县| 苏尼特左旗| 射阳县| 定边县| 定远县| 若尔盖县| 松原市| 石渠县| 绥芬河市| 津南区| 定南县| 邳州市| 合江县|