gnodet opened a new issue, #13646:
URL: https://github.com/apache/maven/issues/13646
## Context
PR #13539 (fixing #8635) adds Maven 4 API types to expose dependency
resolution events to session listeners. The fix for #8635 itself is a 2-line
change in `LifecycleDependencyResolver` to fire the
`DependencyResolutionResult` on failure too. But the PR also introduces three
new API types (`DependencyResolutionEvent`, `DependencyResolutionEventType`,
`DependencyResolutionListener`) and a specific bridge in `EventSpyImpl`.
This approach doesn't scale: if we later want to expose settings building,
toolchains building, or any other service call to Maven 4 listeners, we'd need
to create another triplet of API types each time.
## Proposal
Instead of per-domain event types, introduce a single generic `RequestEvent`
that covers the lifecycle of any service call. All Maven 4 service requests
already extend `Request<S>` and all results extend `Result<REQ>`, so the event
can be properly typed through the existing hierarchy.
### Event
```java
@Experimental
@Immutable
public interface RequestEvent extends Event {
enum Type { SUBMITTED, FULFILLED, FAILED }
Type type();
Request<?> request();
Optional<Result<?>> result(); // empty for SUBMITTED
Optional<Exception> exception(); // for FAILED
}
```
### Listener hierarchy
A generic `RequestListener` filters `Event` → `RequestEvent` and dispatches
to typed callbacks:
```java
@Experimental
@Consumer
public interface RequestListener extends Listener {
@Override
default void onEvent(Event event) {
if (event instanceof RequestEvent re) {
switch (re.type()) {
case SUBMITTED -> requestSubmitted(re);
case FULFILLED -> requestFulfilled(re);
case FAILED -> requestFailed(re);
}
}
}
default void requestSubmitted(RequestEvent event) {}
default void requestFulfilled(RequestEvent event) {}
default void requestFailed(RequestEvent event) {}
}
```
Specialized listeners extend `RequestListener` and further filter by request
type, providing convenient domain-specific callbacks:
```java
@Experimental
@Consumer
public interface DependencyResolutionListener extends RequestListener {
@Override
default void requestSubmitted(RequestEvent event) {
if (event.request() instanceof DependencyResolverRequest) {
dependencyResolutionSubmitted(event);
}
}
@Override
default void requestFulfilled(RequestEvent event) {
if (event.request() instanceof DependencyResolverRequest) {
dependencyResolutionFulfilled(event);
}
}
@Override
default void requestFailed(RequestEvent event) {
if (event.request() instanceof DependencyResolverRequest) {
dependencyResolutionFailed(event);
}
}
default void dependencyResolutionSubmitted(RequestEvent event) {}
default void dependencyResolutionFulfilled(RequestEvent event) {}
default void dependencyResolutionFailed(RequestEvent event) {}
}
```
### Benefits
- **One reusable event type** instead of per-domain event + enum pairs.
- **Properly typed** through the existing `Request`/`Result` hierarchy.
- **Extensible**: adding a `SettingsBuilderListener` later only requires the
listener interface, not a new event type.
- **`RequestListener` is useful on its own** for cross-cutting
monitoring/observability (timing all service calls, logging).
- **Same developer experience** for implementors: `implements
DependencyResolutionListener` and override only the callbacks you care about.
- Follows the same layering pattern already established by `Listener` →
`ExecutionListener` / `RepositoryListener`.
_Claude Code on behalf of Guillaume Nodet_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]