Gangmax Blog

Groovy Grape

From here and here.

Groovy Grape is Groovy’s dependency manager. A big difference between Grape and other language dependency managers like pip, gem and npm is that, it uses language element(annoation, method call) to describe the dependencies inside a Groovy file, rather than a file out of the program itself like “requirements.txt”, “Gemfile” and “package.json”.

For example, let’s say you have a Groovy environment already, in my case it’s Groovy 2.4.15, create the files below in the same directory:

server.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Grapes([
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-server', version='8.1.7.v20120910'),
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-servlet', version='8.1.7.v20120910'),
@Grab(group='javax.servlet', module='javax.servlet-api', version='3.0.1')])

import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.*
import groovy.servlet.*

def runServer(duration) {
def server = new Server(8080)
def context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
context.resourceBase = "."
context.addServlet(TemplateServlet, "*.gsp")
server.start()
sleep duration
server.stop()
}

runServer(10000000000000)
index.gsp
1
This is the index page, under construction.

Now you can run the “server.groovy” in one command like belong, which starts a Jetty server. You can access it in a browser with the URL “http://localhost:8080/index.gsp“.

1
groovy server.groovy

Note that:

  1. When running the program for the first time, it may takes a long time like a dozen of seconds. But for the second time or later, it only takes one or two seconds to start. In fact, the reason of first time slow is that, Groovy intepreter reads the Grape configuration in the Groovy file and downloads the dependencies from remote and save to local disk(“~/.groovy/grapes”) if it cannot find the artifact locally. For the second time or later, it will load them from disk directly.

  2. Note the “@Grapes” annotation, that’s where the dependencies information defines. The “group/module/version” are the “groupId/artifactId/version” concepts in Maven. You can ever use shorthand notation like “@Grab(‘org.springframework:spring-orm:3.2.5.RELEASE’)”. More details can be found here.

  3. You can use the “grape list” command to list the locally installed modules. As mentioned, by default the modules are installed at “~/.groovy/grapes/“ directory.

  4. You have several ways to use Grape to download the dependencies before running your program. Annotation is one of them. And you can also do it by:

  • Explicit method call in your program. Code snippet below.
1
2
3
4
5
import groovy.grape.Grape
// random maven library
Grape.grab(group:'com.jidesoft', module:'jide-oss', version:'[2.2.0,)')
Grape.grab([group:'org.apache.ivy', module:'ivy', version:'2.0.0-beta1', conf:['default', 'optional']],
[group:'org.apache.ant', module:'ant', version:'1.7.0'])
  • Run command line tool.
1
grape install <groupId> <artifactId> [<version>]

For me Grape is special because comparing to the equivalents of the other languages, Grape is a feature provided as an ordinary library and can be used as ordinary code inside a program written in the language, instead of an extra part out of the program itself. This fact makes the feature simpler in concept and more flexible to implement interesting things, like customizing your released artifacts without packaging the whole dependencies, just release your pure code logic and download dependencies according to different users’ requirement.

This makes me think of Lisp.

Comments