or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-compilation.mdcollections-utilities.mdconfig-data.mdcore-language.mddependency-management.mdindex.mdio-file-processing.mdjson-processing.mdsql-database.mdtemplate-engines.mdtesting-apis.mdtime-date.mdtransform-annotations.mdxml-processing.md

dependency-management.mddocs/

0

# Dependency Management

1

2

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.

3

4

## Capabilities

5

6

### Grape Core API

7

8

Main API for programmatic dependency management.

9

10

```java { .api }

11

class Grape {

12

/**

13

* Grabs a dependency using string notation.

14

*/

15

static void grab(String endorsedModule);

16

17

/**

18

* Grabs a dependency using map notation.

19

*/

20

static void grab(Map<String, Object> dependency);

21

22

/**

23

* Grabs multiple dependencies.

24

*/

25

static void grab(Map<String, Object>... dependencies);

26

27

/**

28

* Grabs dependencies with custom class loader.

29

*/

30

static void grab(ClassLoader loader, Map<String, Object>... dependencies);

31

32

/**

33

* Adds a repository resolver.

34

*/

35

static void addResolver(Map<String, Object> args);

36

37

/**

38

* Resolves dependencies to URIs without loading.

39

*/

40

static URI[] resolve(Map<String, Object> args);

41

42

/**

43

* Resolves dependencies to URIs with custom settings.

44

*/

45

static URI[] resolve(Map<String, Object> args, URI... uris);

46

47

/**

48

* Lists available dependencies in the grape cache.

49

*/

50

static Map<String, Map<String, List<String>>> enumerateGrapes();

51

52

/**

53

* Gets the instance of the grape engine.

54

*/

55

static GrapeEngine getInstance();

56

57

/**

58

* Sets the instance of the grape engine.

59

*/

60

static void setInstance(GrapeEngine engine);

61

}

62

```

63

64

### Grape Engine Interface

65

66

Interface for custom grape implementations.

67

68

```java { .api }

69

interface GrapeEngine {

70

/**

71

* Grabs a dependency.

72

*/

73

void grab(Map<String, Object> dependency);

74

75

/**

76

* Grabs dependencies with custom class loader.

77

*/

78

void grab(ClassLoader loader, Map<String, Object> dependency);

79

80

/**

81

* Adds a repository resolver.

82

*/

83

void addResolver(Map<String, Object> args);

84

85

/**

86

* Resolves dependencies to URIs.

87

*/

88

URI[] resolve(Map<String, Object> args);

89

90

/**

91

* Resolves dependencies with custom URIs.

92

*/

93

URI[] resolve(Map<String, Object> args, URI... uris);

94

95

/**

96

* Lists available dependencies.

97

*/

98

Map<String, Map<String, List<String>>> enumerateGrapes();

99

}

100

```

101

102

### Grab Annotations

103

104

Annotations for declarative dependency management in scripts.

105

106

```java { .api }

107

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})

108

@Retention(RetentionPolicy.SOURCE)

109

@interface Grab {

110

/**

111

* The group ID of the dependency.

112

*/

113

String group() default "";

114

115

/**

116

* The module/artifact ID of the dependency.

117

*/

118

String module();

119

120

/**

121

* The version of the dependency.

122

*/

123

String version();

124

125

/**

126

* The classifier of the dependency.

127

*/

128

String classifier() default "";

129

130

/**

131

* The extension/type of the dependency.

132

*/

133

String ext() default "";

134

135

/**

136

* The configuration to use.

137

*/

138

String conf() default "";

139

140

/**

141

* Whether to force the version.

142

*/

143

boolean force() default false;

144

145

/**

146

* Whether to include transitive dependencies.

147

*/

148

boolean transitive() default true;

149

150

/**

151

* Whether to change the class loader.

152

*/

153

boolean changing() default false;

154

155

/**

156

* Modules to exclude from transitive dependencies.

157

*/

158

GrabExclude[] excludes() default {};

159

}

160

161

@Target({})

162

@Retention(RetentionPolicy.SOURCE)

163

@interface GrabExclude {

164

/**

165

* The group ID to exclude.

166

*/

167

String group() default "";

168

169

/**

170

* The module ID to exclude.

171

*/

172

String module() default "";

173

}

174

175

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})

176

@Retention(RetentionPolicy.SOURCE)

177

@interface Grapes {

178

/**

179

* Array of @Grab annotations.

180

*/

181

Grab[] value();

182

}

183

184

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})

185

@Retention(RetentionPolicy.SOURCE)

186

@interface GrabResolver {

187

/**

188

* The name of the repository.

189

*/

190

String name() default "";

191

192

/**

193

* The root URL of the repository.

194

*/

195

String root() default "";

196

197

/**

198

* Whether to use M2 compatible layout.

199

*/

200

boolean m2Compatible() default true;

201

}

202

203

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})

204

@Retention(RetentionPolicy.SOURCE)

205

@interface GrabConfig {

206

/**

207

* System properties to set.

208

*/

209

String[] systemProperties() default {};

210

211

/**

212

* Whether to validate signatures.

213

*/

214

boolean disableChecksums() default false;

215

216

/**

217

* Whether to auto download sources.

218

*/

219

boolean autoDownload() default true;

220

}

221

```

222

223

### AST Transformation Support

224

225

AST transformations that process Grab annotations.

226

227

```java { .api }

228

class GrabAnnotationTransformation implements ASTTransformation {

229

/**

230

* Processes @Grab annotations during compilation.

231

*/

232

void visit(ASTNode[] nodes, SourceUnit source);

233

234

/**

235

* Extracts grab information from annotations.

236

*/

237

Map<String, Object> extractGrabInfo(AnnotationNode annotation);

238

239

/**

240

* Resolves and loads dependencies.

241

*/

242

void processGrabs(List<Map<String, Object>> grabs, ClassLoader loader);

243

}

244

245

class GrabResolverTransformation implements ASTTransformation {

246

/**

247

* Processes @GrabResolver annotations during compilation.

248

*/

249

void visit(ASTNode[] nodes, SourceUnit source);

250

}

251

```

252

253

## Usage Examples

254

255

### Basic Dependency Grabbing

256

257

```java

258

import groovy.grape.Grape;

259

260

// Grab a dependency programmatically using map notation

261

Map<String, Object> dependency = new HashMap<>();

262

dependency.put("group", "commons-lang");

263

dependency.put("module", "commons-lang");

264

dependency.put("version", "2.6");

265

266

Grape.grab(dependency);

267

268

// Now use the grabbed library

269

// This would work in a Groovy script context

270

// import org.apache.commons.lang.StringUtils;

271

// System.out.println(StringUtils.capitalize("hello world"));

272

273

// Grab using string notation (Groovy style)

274

// Grape.grab("commons-lang:commons-lang:2.6");

275

276

// Grab multiple dependencies at once

277

Map<String, Object> httpClient = new HashMap<>();

278

httpClient.put("group", "org.apache.httpcomponents");

279

httpClient.put("module", "httpclient");

280

httpClient.put("version", "4.5.13");

281

282

Map<String, Object> gson = new HashMap<>();

283

gson.put("group", "com.google.code.gson");

284

gson.put("module", "gson");

285

gson.put("version", "2.8.9");

286

287

Grape.grab(httpClient, gson);

288

```

289

290

### Using Grab Annotations in Scripts

291

292

```java

293

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

294

295

@Grab('commons-lang:commons-lang:2.6')

296

@Grab('com.google.code.gson:gson:2.8.9')

297

import org.apache.commons.lang.StringUtils

298

import com.google.gson.Gson

299

300

// Multiple grabs can be combined

301

@Grapes([

302

@Grab('org.apache.httpcomponents:httpclient:4.5.13'),

303

@Grab('org.apache.commons:commons-csv:1.9.0')

304

])

305

import org.apache.http.client.HttpClient

306

import org.apache.commons.csv.CSVFormat

307

308

// Script code using the grabbed dependencies

309

String text = "hello world"

310

String capitalized = StringUtils.capitalize(text)

311

println capitalized

312

313

Gson gson = new Gson()

314

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

315

println json

316

```

317

318

### Advanced Dependency Configuration

319

320

```java

321

import groovy.grape.Grape;

322

import java.util.Map;

323

import java.util.HashMap;

324

325

// Grab with exclusions

326

Map<String, Object> springDep = new HashMap<>();

327

springDep.put("group", "org.springframework");

328

springDep.put("module", "spring-context");

329

springDep.put("version", "5.3.21");

330

springDep.put("transitive", true);

331

332

// Add exclusions for transitive dependencies

333

Map<String, Object> exclude1 = new HashMap<>();

334

exclude1.put("group", "commons-logging");

335

exclude1.put("module", "commons-logging");

336

337

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

338

339

Grape.grab(springDep);

340

341

// Grab with specific classifier

342

Map<String, Object> sourceDep = new HashMap<>();

343

sourceDep.put("group", "org.apache.commons");

344

sourceDep.put("module", "commons-lang3");

345

sourceDep.put("version", "3.12.0");

346

sourceDep.put("classifier", "sources");

347

348

Grape.grab(sourceDep);

349

350

// Force a specific version

351

Map<String, Object> forcedDep = new HashMap<>();

352

forcedDep.put("group", "junit");

353

forcedDep.put("module", "junit");

354

forcedDep.put("version", "4.13.2");

355

forcedDep.put("force", true);

356

357

Grape.grab(forcedDep);

358

```

359

360

### Custom Repository Configuration

361

362

```java

363

import groovy.grape.Grape;

364

365

// Add a custom Maven repository

366

Map<String, Object> customRepo = new HashMap<>();

367

customRepo.put("name", "spring-milestone");

368

customRepo.put("root", "https://repo.spring.io/milestone");

369

customRepo.put("m2Compatible", true);

370

371

Grape.addResolver(customRepo);

372

373

// Add a custom Ivy repository

374

Map<String, Object> ivyRepo = new HashMap<>();

375

ivyRepo.put("name", "my-ivy-repo");

376

ivyRepo.put("root", "http://my-company.com/ivy-repo");

377

ivyRepo.put("m2Compatible", false);

378

379

Grape.addResolver(ivyRepo);

380

381

// Now grab dependencies from custom repositories

382

Map<String, Object> springDep = new HashMap<>();

383

springDep.put("group", "org.springframework");

384

springDep.put("module", "spring-core");

385

springDep.put("version", "6.0.0-M5");

386

387

Grape.grab(springDep);

388

```

389

390

### Annotation-based Repository Configuration

391

392

```java

393

// In a Groovy script:

394

395

@GrabResolver(name='spring-milestones', root='https://repo.spring.io/milestone')

396

@GrabResolver(name='jcenter', root='https://jcenter.bintray.com/')

397

@Grab('org.springframework:spring-context:5.3.21')

398

@Grab(group='org.apache.commons', module='commons-lang3', version='3.12.0')

399

import org.springframework.context.ApplicationContext

400

import org.apache.commons.lang3.StringUtils

401

402

// Use the grabbed dependencies

403

println StringUtils.isBlank("") // true

404

println StringUtils.capitalize("hello") // Hello

405

```

406

407

### Dependency Resolution Without Loading

408

409

```java

410

import groovy.grape.Grape;

411

import java.net.URI;

412

413

// Resolve dependencies to get their file locations without loading

414

Map<String, Object> resolveArgs = new HashMap<>();

415

resolveArgs.put("group", "commons-lang");

416

resolveArgs.put("module", "commons-lang");

417

resolveArgs.put("version", "2.6");

418

419

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

420

421

System.out.println("Resolved dependencies:");

422

for (URI uri : resolvedUris) {

423

System.out.println(" " + uri.toString());

424

}

425

426

// Resolve with multiple dependencies

427

Map<String, Object> dep1 = new HashMap<>();

428

dep1.put("group", "org.apache.commons");

429

dep1.put("module", "commons-csv");

430

dep1.put("version", "1.9.0");

431

432

Map<String, Object> dep2 = new HashMap<>();

433

dep2.put("group", "com.fasterxml.jackson.core");

434

dep2.put("module", "jackson-core");

435

dep2.put("version", "2.13.3");

436

437

Map<String, Object> resolveMultiple = new HashMap<>();

438

resolveMultiple.put("dependencies", new Map[]{dep1, dep2});

439

440

URI[] multipleUris = Grape.resolve(resolveMultiple);

441

System.out.println("Multiple resolved dependencies: " + multipleUris.length);

442

```

443

444

### Grape Cache Management

445

446

```java

447

import groovy.grape.Grape;

448

import java.util.Map;

449

450

// List all grapes in the cache

451

Map<String, Map<String, List<String>>> grapeCache = Grape.enumerateGrapes();

452

453

System.out.println("Grapes in cache:");

454

for (Map.Entry<String, Map<String, List<String>>> groupEntry : grapeCache.entrySet()) {

455

String group = groupEntry.getKey();

456

System.out.println("Group: " + group);

457

458

Map<String, List<String>> modules = groupEntry.getValue();

459

for (Map.Entry<String, List<String>> moduleEntry : modules.entrySet()) {

460

String module = moduleEntry.getKey();

461

List<String> versions = moduleEntry.getValue();

462

System.out.println(" Module: " + module);

463

System.out.println(" Versions: " + versions);

464

}

465

}

466

```

467

468

### Error Handling and Debugging

469

470

```java

471

import groovy.grape.Grape;

472

473

try {

474

// Attempt to grab a dependency that might not exist

475

Map<String, Object> badDep = new HashMap<>();

476

badDep.put("group", "com.nonexistent");

477

badDep.put("module", "fake-library");

478

badDep.put("version", "1.0.0");

479

480

Grape.grab(badDep);

481

482

} catch (Exception e) {

483

System.err.println("Failed to grab dependency: " + e.getMessage());

484

e.printStackTrace();

485

}

486

487

// Set system properties for debugging

488

System.setProperty("groovy.grape.report.downloads", "true");

489

System.setProperty("ivy.message.logger.level", "3"); // Verbose logging

490

491

// Grab with debugging enabled

492

Map<String, Object> debugDep = new HashMap<>();

493

debugDep.put("group", "org.slf4j");

494

debugDep.put("module", "slf4j-simple");

495

debugDep.put("version", "1.7.36");

496

497

Grape.grab(debugDep);

498

```

499

500

### Integration with Build Tools

501

502

```java

503

// Example of programmatic grape usage in a build script context

504

import groovy.grape.Grape;

505

506

// Configure grape for build environment

507

Map<String, Object> mavenCentral = new HashMap<>();

508

mavenCentral.put("name", "central");

509

mavenCentral.put("root", "https://repo1.maven.org/maven2/");

510

mavenCentral.put("m2Compatible", true);

511

512

Grape.addResolver(mavenCentral);

513

514

// Grab build-time dependencies

515

Map<String, Object> antDep = new HashMap<>();

516

antDep.put("group", "org.apache.ant");

517

antDep.put("module", "ant");

518

antDep.put("version", "1.10.12");

519

antDep.put("transitive", false);

520

521

Grape.grab(antDep);

522

523

// Now use Ant tasks programmatically

524

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

525

```

526

527

### Dynamic Class Loading with Grabbed Dependencies

528

529

```java

530

import groovy.grape.Grape;

531

import groovy.lang.GroovyClassLoader;

532

533

// Create a custom class loader

534

GroovyClassLoader classLoader = new GroovyClassLoader();

535

536

// Grab dependencies into the custom class loader

537

Map<String, Object> commonsIo = new HashMap<>();

538

commonsIo.put("group", "commons-io");

539

commonsIo.put("module", "commons-io");

540

commonsIo.put("version", "2.11.0");

541

542

Grape.grab(classLoader, commonsIo);

543

544

// Now classes from commons-io should be available in the classLoader

545

// This enables isolation of dependencies per class loader

546

547

try {

548

Class<?> fileUtilsClass = classLoader.loadClass("org.apache.commons.io.FileUtils");

549

System.out.println("Successfully loaded: " + fileUtilsClass.getName());

550

551

// You could now use reflection to call methods on this class

552

// or compile and execute Groovy code that uses it

553

554

} catch (ClassNotFoundException e) {

555

System.err.println("Failed to load class: " + e.getMessage());

556

}

557

```