CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-codehaus-groovy--groovy

Apache Groovy is a powerful multi-faceted programming language for the JVM platform

Pending
Overview
Eval results
Files

dependency-management.mddocs/

Dependency Management

Grape dependency management system for dynamic dependency resolution and loading, including @Grab annotation support for declaring dependencies in scripts. This system allows Groovy scripts to automatically download and use external libraries at runtime.

Capabilities

Grape Core API

Main API for programmatic dependency management.

class Grape {
    /**
     * Grabs a dependency using string notation.
     */
    static void grab(String endorsedModule);
    
    /**
     * Grabs a dependency using map notation.
     */
    static void grab(Map<String, Object> dependency);
    
    /**
     * Grabs multiple dependencies.
     */
    static void grab(Map<String, Object>... dependencies);
    
    /**
     * Grabs dependencies with custom class loader.
     */
    static void grab(ClassLoader loader, Map<String, Object>... dependencies);
    
    /**
     * Adds a repository resolver.
     */
    static void addResolver(Map<String, Object> args);
    
    /**
     * Resolves dependencies to URIs without loading.
     */
    static URI[] resolve(Map<String, Object> args);
    
    /**
     * Resolves dependencies to URIs with custom settings.
     */
    static URI[] resolve(Map<String, Object> args, URI... uris);
    
    /**
     * Lists available dependencies in the grape cache.
     */
    static Map<String, Map<String, List<String>>> enumerateGrapes();
    
    /**
     * Gets the instance of the grape engine.
     */
    static GrapeEngine getInstance();
    
    /**
     * Sets the instance of the grape engine.
     */
    static void setInstance(GrapeEngine engine);
}

Grape Engine Interface

Interface for custom grape implementations.

interface GrapeEngine {
    /**
     * Grabs a dependency.
     */
    void grab(Map<String, Object> dependency);
    
    /**
     * Grabs dependencies with custom class loader.
     */
    void grab(ClassLoader loader, Map<String, Object> dependency);
    
    /**
     * Adds a repository resolver.
     */
    void addResolver(Map<String, Object> args);
    
    /**
     * Resolves dependencies to URIs.
     */
    URI[] resolve(Map<String, Object> args);
    
    /**
     * Resolves dependencies with custom URIs.
     */
    URI[] resolve(Map<String, Object> args, URI... uris);
    
    /**
     * Lists available dependencies.
     */
    Map<String, Map<String, List<String>>> enumerateGrapes();
}

Grab Annotations

Annotations for declarative dependency management in scripts.

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@interface Grab {
    /**
     * The group ID of the dependency.
     */
    String group() default "";
    
    /**
     * The module/artifact ID of the dependency.
     */
    String module();
    
    /**
     * The version of the dependency.
     */
    String version();
    
    /**
     * The classifier of the dependency.
     */
    String classifier() default "";
    
    /**
     * The extension/type of the dependency.
     */
    String ext() default "";
    
    /**
     * The configuration to use.
     */
    String conf() default "";
    
    /**
     * Whether to force the version.
     */
    boolean force() default false;
    
    /**
     * Whether to include transitive dependencies.
     */
    boolean transitive() default true;
    
    /**
     * Whether to change the class loader.
     */
    boolean changing() default false;
    
    /**
     * Modules to exclude from transitive dependencies.
     */
    GrabExclude[] excludes() default {};
}

@Target({})
@Retention(RetentionPolicy.SOURCE)
@interface GrabExclude {
    /**
     * The group ID to exclude.
     */
    String group() default "";
    
    /**
     * The module ID to exclude.
     */
    String module() default "";
}

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@interface Grapes {
    /**
     * Array of @Grab annotations.
     */
    Grab[] value();
}

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@interface GrabResolver {
    /**
     * The name of the repository.
     */
    String name() default "";
    
    /**
     * The root URL of the repository.
     */
    String root() default "";
    
    /**
     * Whether to use M2 compatible layout.
     */
    boolean m2Compatible() default true;
}

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@interface GrabConfig {
    /**
     * System properties to set.
     */
    String[] systemProperties() default {};
    
    /**
     * Whether to validate signatures.
     */
    boolean disableChecksums() default false;
    
    /**
     * Whether to auto download sources.
     */
    boolean autoDownload() default true;
}

AST Transformation Support

AST transformations that process Grab annotations.

class GrabAnnotationTransformation implements ASTTransformation {
    /**
     * Processes @Grab annotations during compilation.
     */
    void visit(ASTNode[] nodes, SourceUnit source);
    
    /**
     * Extracts grab information from annotations.
     */
    Map<String, Object> extractGrabInfo(AnnotationNode annotation);
    
    /**
     * Resolves and loads dependencies.
     */
    void processGrabs(List<Map<String, Object>> grabs, ClassLoader loader);
}

class GrabResolverTransformation implements ASTTransformation {
    /**
     * Processes @GrabResolver annotations during compilation.
     */
    void visit(ASTNode[] nodes, SourceUnit source);
}

Usage Examples

Basic Dependency Grabbing

import groovy.grape.Grape;

// Grab a dependency programmatically using map notation
Map<String, Object> dependency = new HashMap<>();
dependency.put("group", "commons-lang");
dependency.put("module", "commons-lang");
dependency.put("version", "2.6");

Grape.grab(dependency);

// Now use the grabbed library
// This would work in a Groovy script context
// import org.apache.commons.lang.StringUtils;
// System.out.println(StringUtils.capitalize("hello world"));

// Grab using string notation (Groovy style)
// Grape.grab("commons-lang:commons-lang:2.6");

// Grab multiple dependencies at once
Map<String, Object> httpClient = new HashMap<>();
httpClient.put("group", "org.apache.httpcomponents");
httpClient.put("module", "httpclient");
httpClient.put("version", "4.5.13");

Map<String, Object> gson = new HashMap<>();
gson.put("group", "com.google.code.gson");
gson.put("module", "gson");
gson.put("version", "2.8.9");

Grape.grab(httpClient, gson);

Using Grab Annotations in Scripts

// In a Groovy script (.groovy file):

@Grab('commons-lang:commons-lang:2.6')
@Grab('com.google.code.gson:gson:2.8.9')
import org.apache.commons.lang.StringUtils
import com.google.gson.Gson

// Multiple grabs can be combined
@Grapes([
    @Grab('org.apache.httpcomponents:httpclient:4.5.13'),
    @Grab('org.apache.commons:commons-csv:1.9.0')
])
import org.apache.http.client.HttpClient
import org.apache.commons.csv.CSVFormat

// Script code using the grabbed dependencies
String text = "hello world"
String capitalized = StringUtils.capitalize(text)
println capitalized

Gson gson = new Gson()
String json = gson.toJson([name: "John", age: 30])
println json

Advanced Dependency Configuration

import groovy.grape.Grape;
import java.util.Map;
import java.util.HashMap;

// Grab with exclusions
Map<String, Object> springDep = new HashMap<>();
springDep.put("group", "org.springframework");
springDep.put("module", "spring-context");
springDep.put("version", "5.3.21");
springDep.put("transitive", true);

// Add exclusions for transitive dependencies
Map<String, Object> exclude1 = new HashMap<>();
exclude1.put("group", "commons-logging");
exclude1.put("module", "commons-logging");

springDep.put("excludes", new Map[]{exclude1});

Grape.grab(springDep);

// Grab with specific classifier
Map<String, Object> sourceDep = new HashMap<>();
sourceDep.put("group", "org.apache.commons");
sourceDep.put("module", "commons-lang3");
sourceDep.put("version", "3.12.0");
sourceDep.put("classifier", "sources");

Grape.grab(sourceDep);

// Force a specific version
Map<String, Object> forcedDep = new HashMap<>();
forcedDep.put("group", "junit");
forcedDep.put("module", "junit");
forcedDep.put("version", "4.13.2");
forcedDep.put("force", true);

Grape.grab(forcedDep);

Custom Repository Configuration

import groovy.grape.Grape;

// Add a custom Maven repository
Map<String, Object> customRepo = new HashMap<>();
customRepo.put("name", "spring-milestone");
customRepo.put("root", "https://repo.spring.io/milestone");
customRepo.put("m2Compatible", true);

Grape.addResolver(customRepo);

// Add a custom Ivy repository
Map<String, Object> ivyRepo = new HashMap<>();
ivyRepo.put("name", "my-ivy-repo");
ivyRepo.put("root", "http://my-company.com/ivy-repo");
ivyRepo.put("m2Compatible", false);

Grape.addResolver(ivyRepo);

// Now grab dependencies from custom repositories
Map<String, Object> springDep = new HashMap<>();
springDep.put("group", "org.springframework");
springDep.put("module", "spring-core");
springDep.put("version", "6.0.0-M5");

Grape.grab(springDep);

Annotation-based Repository Configuration

// In a Groovy script:

@GrabResolver(name='spring-milestones', root='https://repo.spring.io/milestone')
@GrabResolver(name='jcenter', root='https://jcenter.bintray.com/')
@Grab('org.springframework:spring-context:5.3.21')
@Grab(group='org.apache.commons', module='commons-lang3', version='3.12.0')
import org.springframework.context.ApplicationContext
import org.apache.commons.lang3.StringUtils

// Use the grabbed dependencies
println StringUtils.isBlank("")  // true
println StringUtils.capitalize("hello")  // Hello

Dependency Resolution Without Loading

import groovy.grape.Grape;
import java.net.URI;

// Resolve dependencies to get their file locations without loading
Map<String, Object> resolveArgs = new HashMap<>();
resolveArgs.put("group", "commons-lang");
resolveArgs.put("module", "commons-lang");
resolveArgs.put("version", "2.6");

URI[] resolvedUris = Grape.resolve(resolveArgs);

System.out.println("Resolved dependencies:");
for (URI uri : resolvedUris) {
    System.out.println("  " + uri.toString());
}

// Resolve with multiple dependencies
Map<String, Object> dep1 = new HashMap<>();
dep1.put("group", "org.apache.commons");
dep1.put("module", "commons-csv");
dep1.put("version", "1.9.0");

Map<String, Object> dep2 = new HashMap<>();
dep2.put("group", "com.fasterxml.jackson.core");
dep2.put("module", "jackson-core");
dep2.put("version", "2.13.3");

Map<String, Object> resolveMultiple = new HashMap<>();
resolveMultiple.put("dependencies", new Map[]{dep1, dep2});

URI[] multipleUris = Grape.resolve(resolveMultiple);
System.out.println("Multiple resolved dependencies: " + multipleUris.length);

Grape Cache Management

import groovy.grape.Grape;
import java.util.Map;

// List all grapes in the cache
Map<String, Map<String, List<String>>> grapeCache = Grape.enumerateGrapes();

System.out.println("Grapes in cache:");
for (Map.Entry<String, Map<String, List<String>>> groupEntry : grapeCache.entrySet()) {
    String group = groupEntry.getKey();
    System.out.println("Group: " + group);
    
    Map<String, List<String>> modules = groupEntry.getValue();
    for (Map.Entry<String, List<String>> moduleEntry : modules.entrySet()) {
        String module = moduleEntry.getKey();
        List<String> versions = moduleEntry.getValue();
        System.out.println("  Module: " + module);
        System.out.println("    Versions: " + versions);
    }
}

Error Handling and Debugging

import groovy.grape.Grape;

try {
    // Attempt to grab a dependency that might not exist
    Map<String, Object> badDep = new HashMap<>();
    badDep.put("group", "com.nonexistent");
    badDep.put("module", "fake-library");
    badDep.put("version", "1.0.0");
    
    Grape.grab(badDep);
    
} catch (Exception e) {
    System.err.println("Failed to grab dependency: " + e.getMessage());
    e.printStackTrace();
}

// Set system properties for debugging
System.setProperty("groovy.grape.report.downloads", "true");
System.setProperty("ivy.message.logger.level", "3"); // Verbose logging

// Grab with debugging enabled
Map<String, Object> debugDep = new HashMap<>();
debugDep.put("group", "org.slf4j");
debugDep.put("module", "slf4j-simple");
debugDep.put("version", "1.7.36");

Grape.grab(debugDep);

Integration with Build Tools

// Example of programmatic grape usage in a build script context
import groovy.grape.Grape;

// Configure grape for build environment
Map<String, Object> mavenCentral = new HashMap<>();
mavenCentral.put("name", "central");
mavenCentral.put("root", "https://repo1.maven.org/maven2/");
mavenCentral.put("m2Compatible", true);

Grape.addResolver(mavenCentral);

// Grab build-time dependencies
Map<String, Object> antDep = new HashMap<>();
antDep.put("group", "org.apache.ant");
antDep.put("module", "ant");
antDep.put("version", "1.10.12");
antDep.put("transitive", false);

Grape.grab(antDep);

// Now use Ant tasks programmatically
// This would be in a Groovy context where you could import and use Ant

Dynamic Class Loading with Grabbed Dependencies

import groovy.grape.Grape;
import groovy.lang.GroovyClassLoader;

// Create a custom class loader
GroovyClassLoader classLoader = new GroovyClassLoader();

// Grab dependencies into the custom class loader
Map<String, Object> commonsIo = new HashMap<>();
commonsIo.put("group", "commons-io");
commonsIo.put("module", "commons-io");
commonsIo.put("version", "2.11.0");

Grape.grab(classLoader, commonsIo);

// Now classes from commons-io should be available in the classLoader
// This enables isolation of dependencies per class loader

try {
    Class<?> fileUtilsClass = classLoader.loadClass("org.apache.commons.io.FileUtils");
    System.out.println("Successfully loaded: " + fileUtilsClass.getName());
    
    // You could now use reflection to call methods on this class
    // or compile and execute Groovy code that uses it
    
} catch (ClassNotFoundException e) {
    System.err.println("Failed to load class: " + e.getMessage());
}

Install with Tessl CLI

npx tessl i tessl/maven-org-codehaus-groovy--groovy

docs

ast-compilation.md

collections-utilities.md

config-data.md

core-language.md

dependency-management.md

index.md

io-file-processing.md

json-processing.md

sql-database.md

template-engines.md

testing-apis.md

time-date.md

transform-annotations.md

xml-processing.md

tile.json