0
# Resolution and Filtering
1
2
Maven's artifact resolution framework provides exception handling and filtering mechanisms for dependency resolution workflows. This includes a comprehensive exception hierarchy for handling various resolution failures and filtering interfaces for controlling which artifacts are included in resolution processes.
3
4
## Resolution Exception Hierarchy
5
6
### AbstractArtifactResolutionException
7
8
Base class for all artifact resolution exceptions, providing common error information.
9
10
```java { .api }
11
public abstract class AbstractArtifactResolutionException extends Exception {
12
// Artifact information
13
public Artifact getArtifact();
14
public String getGroupId();
15
public String getArtifactId();
16
public String getVersion();
17
public String getType();
18
public String getClassifier();
19
20
// Resolution context
21
public List<ArtifactRepository> getRemoteRepositories();
22
public String getPath();
23
public String getOriginalMessage();
24
25
// Standard exception methods
26
public String getMessage();
27
public String getLocalizedMessage();
28
}
29
```
30
31
**Common Properties**:
32
- **Artifact**: The artifact that failed to resolve
33
- **Remote Repositories**: List of repositories that were searched
34
- **Path**: Dependency path leading to the failed artifact
35
- **Original Message**: Underlying error message
36
37
### ArtifactResolutionException
38
39
General artifact resolution problems not covered by more specific exceptions.
40
41
```java { .api }
42
public class ArtifactResolutionException extends AbstractArtifactResolutionException {
43
public ArtifactResolutionException(String message, Artifact artifact);
44
public ArtifactResolutionException(String message, Artifact artifact,
45
List<ArtifactRepository> remoteRepositories);
46
public ArtifactResolutionException(String message, Artifact artifact,
47
List<ArtifactRepository> remoteRepositories, Throwable cause);
48
public ArtifactResolutionException(String message, Artifact artifact, Throwable cause);
49
}
50
```
51
52
**Common Scenarios**:
53
- Repository connectivity issues
54
- Corrupted artifact files
55
- Permission problems
56
- General I/O errors during resolution
57
58
**Usage Examples**:
59
60
```java
61
try {
62
// Artifact resolution logic
63
resolveArtifact(artifact);
64
} catch (ArtifactResolutionException e) {
65
System.err.println("Failed to resolve: " + e.getArtifact());
66
System.err.println("Searched repositories: " + e.getRemoteRepositories().size());
67
System.err.println("Error: " + e.getMessage());
68
69
// Handle resolution failure
70
handleResolutionFailure(e);
71
}
72
```
73
74
### ArtifactNotFoundException
75
76
Specific exception for artifacts that cannot be found in any searched repository.
77
78
```java { .api }
79
public class ArtifactNotFoundException extends AbstractArtifactResolutionException {
80
public ArtifactNotFoundException(String message, Artifact artifact);
81
public ArtifactNotFoundException(String message, Artifact artifact,
82
List<ArtifactRepository> remoteRepositories);
83
public ArtifactNotFoundException(String message, Artifact artifact,
84
List<ArtifactRepository> remoteRepositories, Throwable cause);
85
86
public String getDownloadUrl();
87
}
88
```
89
90
**Usage Examples**:
91
92
```java
93
try {
94
artifact = findArtifact(coordinates);
95
} catch (ArtifactNotFoundException e) {
96
System.err.println("Artifact not found: " + e.getGroupId() + ":" +
97
e.getArtifactId() + ":" + e.getVersion());
98
99
// Check if download URL is available
100
String downloadUrl = e.getDownloadUrl();
101
if (downloadUrl != null) {
102
System.err.println("Try downloading from: " + downloadUrl);
103
}
104
105
// List searched repositories
106
for (ArtifactRepository repo : e.getRemoteRepositories()) {
107
System.err.println("Searched: " + repo.getUrl());
108
}
109
}
110
```
111
112
### CyclicDependencyException
113
114
Indicates circular dependencies in the dependency graph.
115
116
```java { .api }
117
public class CyclicDependencyException extends ArtifactResolutionException {
118
public CyclicDependencyException(String message, Artifact artifact);
119
public CyclicDependencyException(String message, Artifact artifact,
120
List<ArtifactRepository> remoteRepositories);
121
public CyclicDependencyException(String message, Artifact artifact,
122
List<ArtifactRepository> remoteRepositories, Throwable cause);
123
}
124
```
125
126
**Common Scenarios**:
127
- Direct circular dependency: A -> B -> A
128
- Indirect circular dependency: A -> B -> C -> A
129
- Complex multi-level cycles in large dependency graphs
130
131
**Usage Examples**:
132
133
```java
134
try {
135
List<Artifact> resolved = resolveDependencies(rootArtifact);
136
} catch (CyclicDependencyException e) {
137
System.err.println("Circular dependency detected:");
138
System.err.println("Path: " + e.getPath());
139
System.err.println("Problematic artifact: " + e.getArtifact());
140
141
// Attempt to break cycle by excluding optional dependencies
142
resolveWithExclusions(rootArtifact, e.getArtifact());
143
}
144
```
145
146
### MultipleArtifactsNotFoundException
147
148
Thrown when multiple artifacts cannot be resolved in a batch operation.
149
150
```java { .api }
151
public class MultipleArtifactsNotFoundException extends ArtifactResolutionException {
152
public MultipleArtifactsNotFoundException(Artifact artifact,
153
List<Artifact> resolvedArtifacts,
154
List<Artifact> missingArtifacts,
155
List<ArtifactRepository> remoteRepositories);
156
157
public List<Artifact> getResolvedArtifacts();
158
public List<Artifact> getMissingArtifacts();
159
}
160
```
161
162
**Usage Examples**:
163
164
```java
165
try {
166
List<Artifact> dependencies = Arrays.asList(dep1, dep2, dep3, dep4);
167
resolveArtifacts(dependencies);
168
} catch (MultipleArtifactsNotFoundException e) {
169
List<Artifact> resolved = e.getResolvedArtifacts();
170
List<Artifact> missing = e.getMissingArtifacts();
171
172
System.out.println("Successfully resolved " + resolved.size() + " artifacts:");
173
resolved.forEach(a -> System.out.println(" ✓ " + a));
174
175
System.out.println("Failed to resolve " + missing.size() + " artifacts:");
176
missing.forEach(a -> System.out.println(" ✗ " + a));
177
178
// Continue with partial resolution or fail completely
179
if (resolved.size() > missing.size()) {
180
continueWithPartialDependencies(resolved);
181
} else {
182
throw e; // Re-throw if too many failures
183
}
184
}
185
```
186
187
## Artifact Filtering
188
189
### ArtifactFilter Interface
190
191
Interface for filtering artifacts during resolution processes.
192
193
```java { .api }
194
public interface ArtifactFilter {
195
boolean include(Artifact artifact);
196
}
197
```
198
199
**Usage Examples**:
200
201
```java
202
// Filter by scope
203
ArtifactFilter scopeFilter = new ArtifactFilter() {
204
@Override
205
public boolean include(Artifact artifact) {
206
String scope = artifact.getScope();
207
return Artifact.SCOPE_COMPILE.equals(scope) ||
208
Artifact.SCOPE_RUNTIME.equals(scope);
209
}
210
};
211
212
// Filter by type
213
ArtifactFilter typeFilter = artifact -> "jar".equals(artifact.getType());
214
215
// Filter by group ID pattern
216
ArtifactFilter groupFilter = artifact ->
217
artifact.getGroupId().startsWith("com.company.");
218
219
// Composite filter (AND logic)
220
ArtifactFilter compositeFilter = artifact ->
221
scopeFilter.include(artifact) &&
222
typeFilter.include(artifact) &&
223
groupFilter.include(artifact);
224
225
// Use filter in resolution
226
List<Artifact> filtered = dependencies.stream()
227
.filter(compositeFilter::include)
228
.collect(Collectors.toList());
229
```
230
231
### Common Filter Implementations
232
233
```java
234
// Exclude test dependencies
235
ArtifactFilter excludeTestFilter = artifact ->
236
!Artifact.SCOPE_TEST.equals(artifact.getScope());
237
238
// Include only specific artifact types
239
ArtifactFilter jarAndWarFilter = artifact -> {
240
String type = artifact.getType();
241
return "jar".equals(type) || "war".equals(type);
242
};
243
244
// Exclude snapshot versions
245
ArtifactFilter excludeSnapshotsFilter = artifact ->
246
!ArtifactUtils.isSnapshot(artifact.getVersion());
247
248
// Include only specific groups
249
Set<String> allowedGroups = Set.of("org.apache.maven", "junit", "org.slf4j");
250
ArtifactFilter groupWhitelistFilter = artifact ->
251
allowedGroups.contains(artifact.getGroupId());
252
253
// Exclude artifacts with classifiers
254
ArtifactFilter noClassifierFilter = artifact ->
255
artifact.getClassifier() == null || artifact.getClassifier().isEmpty();
256
```
257
258
## Error Handling Strategies
259
260
### Exception Analysis
261
262
```java
263
public void analyzeResolutionException(Exception e) {
264
if (e instanceof ArtifactNotFoundException) {
265
ArtifactNotFoundException anfe = (ArtifactNotFoundException) e;
266
handleMissingArtifact(anfe);
267
268
} else if (e instanceof CyclicDependencyException) {
269
CyclicDependencyException cde = (CyclicDependencyException) e;
270
handleCircularDependency(cde);
271
272
} else if (e instanceof MultipleArtifactsNotFoundException) {
273
MultipleArtifactsNotFoundException manfe = (MultipleArtifactsNotFoundException) e;
274
handlePartialResolution(manfe);
275
276
} else if (e instanceof OverConstrainedVersionException) {
277
OverConstrainedVersionException ocve = (OverConstrainedVersionException) e;
278
handleVersionConflict(ocve);
279
280
} else if (e instanceof ArtifactResolutionException) {
281
ArtifactResolutionException are = (ArtifactResolutionException) e;
282
handleGeneralResolutionError(are);
283
}
284
}
285
```
286
287
### Recovery Strategies
288
289
```java
290
// Retry with different repositories
291
public Artifact resolveWithFallback(Artifact artifact,
292
List<ArtifactRepository> primaryRepos,
293
List<ArtifactRepository> fallbackRepos) {
294
try {
295
return resolve(artifact, primaryRepos);
296
} catch (ArtifactNotFoundException e) {
297
System.out.println("Primary resolution failed, trying fallback repositories...");
298
return resolve(artifact, fallbackRepos);
299
}
300
}
301
302
// Resolve with exclusions to break cycles
303
public List<Artifact> resolveBreakingCycles(Artifact root, Set<Artifact> excludes) {
304
ArtifactFilter cycleBreaker = artifact -> !excludes.contains(artifact);
305
return resolveWithFilter(root, cycleBreaker);
306
}
307
308
// Partial resolution for build continuation
309
public BuildResult continueWithPartialDependencies(List<Artifact> available) {
310
System.out.println("Continuing build with " + available.size() + " available dependencies");
311
// Mark missing dependencies for later resolution
312
// Continue with available artifacts
313
return buildWithDependencies(available);
314
}
315
```
316
317
### Logging and Diagnostics
318
319
```java
320
// Comprehensive error reporting
321
public void reportResolutionFailure(AbstractArtifactResolutionException e) {
322
System.err.println("=== Artifact Resolution Failure ===");
323
System.err.println("Artifact: " + formatArtifact(e.getArtifact()));
324
System.err.println("Error: " + e.getMessage());
325
326
if (e.getPath() != null) {
327
System.err.println("Dependency Path: " + e.getPath());
328
}
329
330
System.err.println("Searched Repositories:");
331
for (ArtifactRepository repo : e.getRemoteRepositories()) {
332
System.err.println(" - " + repo.getId() + ": " + repo.getUrl());
333
}
334
335
if (e instanceof ArtifactNotFoundException) {
336
ArtifactNotFoundException anfe = (ArtifactNotFoundException) e;
337
if (anfe.getDownloadUrl() != null) {
338
System.err.println("Suggested download: " + anfe.getDownloadUrl());
339
}
340
}
341
342
System.err.println("=====================================");
343
}
344
345
private String formatArtifact(Artifact artifact) {
346
return String.format("%s:%s:%s:%s:%s",
347
artifact.getGroupId(),
348
artifact.getArtifactId(),
349
artifact.getVersion(),
350
artifact.getType(),
351
artifact.getClassifier() != null ? artifact.getClassifier() : "");
352
}
353
```
354
355
## Integration with Resolution Workflows
356
357
### Filter Chain Processing
358
359
```java
360
// Build resolution filter chain
361
List<ArtifactFilter> filterChain = Arrays.asList(
362
excludeTestFilter,
363
jarAndWarFilter,
364
excludeSnapshotsFilter,
365
groupWhitelistFilter
366
);
367
368
// Apply filter chain
369
ArtifactFilter combinedFilter = artifact ->
370
filterChain.stream().allMatch(filter -> filter.include(artifact));
371
372
// Use in resolution process
373
public List<Artifact> resolveWithFilters(Artifact root, ArtifactFilter filter) {
374
List<Artifact> allDependencies = getAllDependencies(root);
375
return allDependencies.stream()
376
.filter(filter::include)
377
.collect(Collectors.toList());
378
}
379
```
380
381
### Exception Propagation
382
383
```java
384
// Exception wrapping for higher-level APIs
385
public class BuildException extends Exception {
386
private final List<AbstractArtifactResolutionException> resolutionFailures;
387
388
public BuildException(String message,
389
List<AbstractArtifactResolutionException> failures) {
390
super(message);
391
this.resolutionFailures = failures;
392
}
393
394
public List<AbstractArtifactResolutionException> getResolutionFailures() {
395
return resolutionFailures;
396
}
397
}
398
399
// Collect and report all resolution issues
400
public void buildProject(List<Artifact> dependencies) throws BuildException {
401
List<AbstractArtifactResolutionException> failures = new ArrayList<>();
402
403
for (Artifact dependency : dependencies) {
404
try {
405
resolve(dependency);
406
} catch (AbstractArtifactResolutionException e) {
407
failures.add(e);
408
}
409
}
410
411
if (!failures.isEmpty()) {
412
throw new BuildException("Dependency resolution failed", failures);
413
}
414
}
415
```