Skip to content

Improve generics matching of ApplicationEvent subtypes with generic payload parameter [SPR-13069] #17661

Closed
@spring-projects-issues

Description

@spring-projects-issues

Oliver Drotbohm opened SPR-13069 and commented

Spring 4.2 introduces better matching of generic types for ApplicationEvent instances. The matching now requires a complete generic match for an event being delivered to an ApplicationListener. Assume the following scenario:

class EventWithPayload<T> {

  public EventWithPayload(T source) {
    super(source);
  }
}

The main purpose of a generic type introduced in an ApplicationEvent is to allow ApplicationListeners to be declared to match that particular type:

class PersonEventListener implements ApplicationListener<EventWithPayload<Person>> { … }

The delivery of instances of such an event now only works if a dedicated sub-type that fills the generic parameter is used (e.g. a new EventWithPayload<Person>(person) {} is thrown). However, if the generic type is used as is, delivery fails as the event type is basically interpreted as EventWithPayload<?> and thus (understandably) doesn't match the generics matching.

I suggest to introduce an annotation that can be used on EventWithPayload to let Spring Framework inspect the event's payload type and include that in the matching algorithm. It basically expresses: "in this event type the generic type is used to bind the payload".

@PayloadGenerics(0) // index of the generic parameter in case multiple ones are use, default to 0
class EventWithPayload<T> { … }

Alternatively, an idea might be to analyze the return type of getSource() and inspect the payload if that method has been overridden to return any of the generic parameters of the type.

class EventWithPayload<T> {

  public EventWithPayload(T source) {
    super(source);
  }

  @Override
  public T getSource() {
    return (T) super.getSource();
  }
}

Affects: 4.2 RC1

Referenced from: commits 06a0dfa, b87816e

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions