A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/pmd/pmd/issues/174 below:

[java] SingularField false positive with switch in method that both assigns and reads field · Issue #174 · pmd/pmd · GitHub

Affects PMD Version: 5.5.1...6.55.0

Rule: SingularField

Description:

I have the following JAX-RS event listener that uses a Prometheus Summary to measure the time of all non-404 responses. It violates the java/design/SingularField rule.

Code Sample demonstrating the issue:

// package, imports

@Provider
public class LatencyRequestEventListener implements RequestEventListener {
    private static final Summary SUMMARY_LATENCY_SECONDS = …;

    private final ResourceInfo resourceInfo;

    private Summary.Timer timer; // BREAKS HERE

    LatencyRequestEventListener(final ResourceInfo resourceInfo) {
        this.resourceInfo = resourceInfo;
    }

    @Override
    public void onEvent(final RequestEvent event) {
        switch (event.getType()) {
            case RESOURCE_METHOD_START:
                final ResourceMethod matchedResourceMethod = event.getUriInfo().getMatchedResourceMethod();

                if (matchedResourceMethod == null) {
                    return;
                }

                timer = SUMMARY_LATENCY_SECONDS // ASSIGN FIELD
                    .labels(
                        matchedResourceMethod.getHttpMethod()
                        , resourceInfo.getResourceClass().getSimpleName() + "." + resourceInfo.getResourceMethod().getName()
                    )
                    .startTimer();
                break; // Don't keep going (both cases cannot be reached in the same call)
            case FINISHED:
                if (timer != null) {
                    timer.observeDuration(); // READ FIELD
                }
        }
    }
}

Expected outcome:

PMD reports a violation at line 25, but that's wrong. That's a false positive.

This results in the following error:

/path/to/project/…/listeners/LatencyRequestEventListener.java:25: Perhaps 'timer' could be replaced by a local variable.

timer can't be a local variable, so I don't think it's correct to report this rule violated.

I understand that the rule is violated if a field is only accessed by a single method. I also acknowledge that having the same method be called twice to first assign a field (the RESOURCE_METHOD_START case) and then read the field (FINISHED) may not be a good design. However, that's how the JAX-RS people designed the RequestEventListener class.

If I pull the code for the RESOURCE_METHOD_START case into a separate method, it passes with no problem since multiple methods access the field.

Is this a bug, or am I doing something wrong?

EDIT: As a funky side note, pulling the configuration of the Timer into a method makes the code legal, despite still only referencing the timer field in onEvent(…):

private static Summary.Child configureTimer(
    final Summary summary,
    final String httpMethod
    , final String handlerName
) {
    return summary
        .labels(httpMethod, handlerName);
}

@Override
public void onEvent(final RequestEvent event) {
    switch (event.getType()) {
        case RESOURCE_METHOD_START:
            final ResourceMethod matchedResourceMethod = event.getUriInfo().getMatchedResourceMethod();
            if (matchedResourceMethod != null) {
                timer = configureTimer(
                    SUMMARY_LATENCY_SECONDS,
                    matchedResourceMethod.getHttpMethod()
                    , resourceInfo.getResourceClass().getSimpleName() + "." + resourceInfo.getResourceMethod().getName()
                ).startTimer();
            }
            break;
        case FINISHED:
            if (timer != null) {
                timer.observeDuration();
            }
    }
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4