Skip to content

[java] UnnecessaryImport with multiple static imports from same class #5852

@Pankraz76

Description

@Pankraz76

Affects PMD Version: 7.14.0

Rule: UnnecessaryImport

Description:

Code Sample demonstrating the issue:

import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime;

[WARNING] PMD Failure: io.quarkus.runtime.configuration.ConfigRecorder:3 Rule:UnnecessaryImport Priority:4 Unused static import 'io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime'.

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-pmd-plugin:3.26.0:check (default-cli) on project quarkus-core: PMD 7.14.0 has found 1 violation. For more details see: /Users/vincent.potucek/IdeaProjects/quarkus/core/runtime/target/pmd.xml
package io.quarkus.runtime.configuration;

import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime; // _not_ unnecessary!!
import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime.fail;
import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime.warn;

// ...
public class ConfigRecorder {
    public void handleConfigChange(Map<String, ConfigValue> buildTimeRuntimeValues) {
            // ...
            BuildTimeMismatchAtRuntime buildTimeMismatchAtRuntime = config
                    .getOptionalValue("quarkus.config.build-time-mismatch-at-runtime", BuildTimeMismatchAtRuntime.class)
                    .orElse(warn);
            if (fail.equals(buildTimeMismatchAtRuntime)) {
                throw new IllegalStateException(msg);
            } else if (warn.equals(buildTimeMismatchAtRuntime)) {
                log.warn(msg);
            }
    }
}
Full source
package io.quarkus.runtime.configuration;

import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime;
import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime.fail;
import static io.quarkus.runtime.ConfigConfig.BuildTimeMismatchAtRuntime.warn;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.logging.Logger;

import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;

@Recorder
public class ConfigRecorder {
    private static final Logger log = Logger.getLogger(ConfigRecorder.class);

    public void handleConfigChange(Map<String, ConfigValue> buildTimeRuntimeValues) {
        SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
        // Disable the BuildTime RunTime Fixed (has the highest ordinal), because a lookup will get the expected value,
        // and we have no idea if the user tried to override it in another source.
        Optional<ConfigSource> builtTimeRunTimeFixedConfigSource = config.getConfigSource("BuildTime RunTime Fixed");
        if (builtTimeRunTimeFixedConfigSource.isPresent()) {
            ConfigSource configSource = builtTimeRunTimeFixedConfigSource.get();
            if (configSource instanceof DisableableConfigSource) {
                ((DisableableConfigSource) configSource).disable();
            }
        }

        List<String> mismatches = new ArrayList<>();
        for (Map.Entry<String, ConfigValue> entry : buildTimeRuntimeValues.entrySet()) {
            ConfigValue currentValue = config.getConfigValue(entry.getKey());
            // Check for changes. Also, we only have a change if the source ordinal is higher
            // The config value can be null (for ex. if the property uses environment variables not available at build time)
            if (currentValue.getValue() != null && !Objects.equals(entry.getValue().getValue(), currentValue.getValue())
                    && entry.getValue().getSourceOrdinal() < currentValue.getSourceOrdinal()) {
                mismatches.add(
                        " - " + entry.getKey() + " is set to '" + currentValue.getValue()
                                + "' but it is build time fixed to '"
                                + entry.getValue().getValue() + "'. Did you change the property " + entry.getKey()
                                + " after building the application?");
            }
        }

        // Enable the BuildTime RunTime Fixed. It should be fine doing these operations, because this is on startup
        if (builtTimeRunTimeFixedConfigSource.isPresent()) {
            ConfigSource configSource = builtTimeRunTimeFixedConfigSource.get();
            if (configSource instanceof DisableableConfigSource) {
                ((DisableableConfigSource) configSource).enable();
            }
        }

        if (!mismatches.isEmpty()) {
            String msg = "Build time property cannot be changed at runtime:\n" + String.join("\n", mismatches);
            // TODO - This should use ConfigConfig, but for some reason, the test fails sometimes with mapping not found when looking ConfigConfig
            BuildTimeMismatchAtRuntime buildTimeMismatchAtRuntime = config
                    .getOptionalValue("quarkus.config.build-time-mismatch-at-runtime", BuildTimeMismatchAtRuntime.class)
                    .orElse(warn);
            if (fail.equals(buildTimeMismatchAtRuntime)) {
                throw new IllegalStateException(msg);
            } else if (warn.equals(buildTimeMismatchAtRuntime)) {
                log.warn(msg);
            }
        }
    }

    public void handleNativeProfileChange(List<String> buildProfiles) {
        SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
        List<String> runtimeProfiles = config.getProfiles();

        if (buildProfiles.size() != runtimeProfiles.size()) {
            log.warn(
                    "The profile '" + buildProfiles + "' used to build the native image is different from the runtime profile '"
                            + runtimeProfiles + "'. This may lead to unexpected results.");
            return;
        }

        for (int i = 0; i < buildProfiles.size(); i++) {
            String buildProfile = buildProfiles.get(i);
            String runtimeProfile = runtimeProfiles.get(i);

            if (!buildProfile.equals(runtimeProfile)) {
                log.warn("The profile '" + buildProfile
                        + "' used to build the native image is different from the runtime profile '" + runtimeProfile
                        + "'. This may lead to unexpected results.");
            }
        }
    }

    public void unknownConfigFiles() throws Exception {
        ConfigDiagnostic.unknownConfigFiles(ConfigDiagnostic.configFilesFromLocations());
    }

    public void releaseConfig(ShutdownContext shutdownContext) {
        // This is mostly useful to handle restarts in Dev/Test mode.
        // While this may seem to duplicate code in IsolatedDevModeMain,
        // it actually does not because it operates on a different instance
        // of QuarkusConfigFactory from a different classloader.

        if (shutdownContext == null) {
            throw new RuntimeException(
                    "Internal errror: shutdownContext is null. This probably happened because Quarkus failed to start properly in an earlier step, or because tests were run on a Quarkus instance that had already been shut down.");
        }
        shutdownContext.addLastShutdownTask(QuarkusConfigFactory::releaseTCCLConfig);
    }
}

Expected outcome:

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

Running PMD through: [Maven]

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:false-positivePMD flags a piece of code that is not problematic

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy