google / google/error-prone

`UnnecessaryQualifier` outputs warnings for CDI observers

Open
#5,173 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
7.2k
Forks
820
Avg merge
5h 9m
Merged PRs (30d)
50

Description

With the reproducer source file below, `UnnecessaryQualifier` in error-prone 2.40.0 reports the following warnings:
1. `[28,4] [UnnecessaryQualifier] A qualifier annotation has no effect here.`
- This is already reported as #5128.
2. `[56,42] [UnnecessaryQualifier] A qualifier annotation has no effect here.`
- This is a new issue. It's a false positive as `Observes` [considers the qualifier](https://docs.oracle.com/javaee/7/api/javax/enterprise/event/Observes.html):
_Each observer method must have exactly one event parameter, of the same type as the event type it observes. Event qualifiers may be declared by annotating the event parameter. When searching for observer methods for an event, the container considers the type and qualifiers of the event parameter._
- The same false positive occurs with the popular `@Observes @Initialized(ApplicationScoped.class)` pattern, which emulates EJB's `@Startup` annotation. See https://www.adam-bien.com/roller/abien/entry/startup_initialization_logic_with_cdi.
``` java
package com.example;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Qualifier;

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;

import com.google.errorprone.annotations.Keep;

@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Inject, access = AccessLevel.PROTECTED)
public final class FooDeleter
{
@Deleted // ⚠️1
private final Event fooDeletedEvent;

public void delete(int fooId)
{
log.info("Deleting Foo {}", fooId);

fooDeletedEvent.fire(null);
}
}

@Qualifier
@Target({ METHOD, FIELD, PARAMETER, TYPE })
@Retention(RUNTIME)
@interface Deleted
{
}

@Value
class Foo
{
int id;
}

@Slf4j
final class DeletionObserver
{
@Keep
private void afterFooDelete(@Observes @Deleted Foo deletedFoo) // ⚠️2
{
log.info("Observed deletion of {}", deletedFoo);
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.