Why does the main Spring Boot application always trigger PMD's HideUtilityClassConstructorCheck?
Asked Answered
H

5

10

The standard Spring Boot application has some main method class file, say SampleApplication.java, that looks like this:

@SpringBootApplication
@RestController
public class SampleApplication {

    public static void main(final String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

}

But PMD static analysis flags it as an error (HideUtilityClassConstructorCheck):

Utility classes should not have a public or default constructor.

Makes sure that utility classes (classes that contain only static methods or fields in their API) do not have a public constructor.

Rationale: Instantiating utility classes does not make sense. Hence the constructors should either be private or (if you want to allow subclassing) protected. A common mistake is forgetting to hide the default constructor.

If you make the constructor protected you may want to consider the following constructor implementation technique to disallow instantiating subclasses:

public class StringUtils // not final to allow subclassing { protected StringUtils() { // prevents calls from subclass throw new UnsupportedOperationException(); } public static int count(char c, String s) { // ... } }

Why is this? Should I be suppressing this PMD error?

Hypophosphite answered 13/5, 2016 at 21:17 Comment(2)
same problem here!Chesterchesterfield
Check this out: Suppress style checks for files.Yanyanaton
S
6

The inspection speaks for itself.

By default any code inspector (IntelliJ IDEA, FindBugs, PMD, Sonar) assumes that if class has only static methods then it's utility class. Example of utility class is java.lang.Math, which looks like this:

public final class Math {

    /**
     * Don't let anyone instantiate this class.
     */
    private Math() {}

    public static double exp(double a) {
        ...
    }

    // More helper methods
}

Such classes are designed for using it as a bag of static functions: it's a good practice to declare private constructor for it, so no one will ever instantiate it by mistake and declare class final, because extending it makes no sense.

In your case (and in case almost every entry point of Spring Boot applications) SampleApplication class has one public static void main method, so PMD decides its utility class, checks private construction and final modifier and flags the error. It's not the problem, PMD just don't know about Spring Boot or any other frameworks and their entry points, so it makes perfect sense to suppress this warning and exclude your class from PMD: for me its more semantically correct than adding private constructor to application entry point.

Shavon answered 13/5, 2016 at 22:28 Comment(1)
any other options?? adding private constructor won't work!Chesterchesterfield
O
4

The PMD UseUtilityClass rule can be suppressed just for classes with @SpringBootApplication annotation using the following snippet in the PMD ruleset XML file:

<rule ref="category/java/design.xml/UseUtilityClass">
    <properties>
        <property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration/preceding-sibling::Annotation/MarkerAnnotation/Name[@Image='SpringBootApplication']" />
    </properties>
</rule>
Ox answered 17/9, 2018 at 21:9 Comment(0)
C
3

You can suppress warnings in your entry point using @SuppressWarnings("PMD"), because Spring Core uses aspect-oriented programming based on reflections and other things which PMD analyzer can't analyze. Don't worry about suppressing warnings in this class

For eaxmple:

@SuppressWarnings("PMD")
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
@EnableScheduling
@EnableConfigurationProperties
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

You can read more here: https://pmd.github.io/latest/pmd_userdocs_suppressing_warnings.html

Cyrus answered 21/2, 2020 at 10:29 Comment(0)
D
3

Now you can just ignore annotation @SpringBootApplication like this:

<rule ref="category/java/design.xml/UseUtilityClass">
    <properties>
        <property name="ignoredAnnotations" value="org.springframework.boot.autoconfigure.SpringBootApplication"/>
    </properties>
</rule>

See UseUtilityClass since PMD 6.16.0 (30-June-2019)

Dropwort answered 21/10, 2020 at 22:54 Comment(1)
Not true anymore since PMD 7.0.0 :(Evictee
D
0

For PMD 7, you can exclude classes annotated with @SpringBootApplication like so:

<rule ref="category/java/design.xml/UseUtilityClass">
  <properties>
    <property name="violationSuppressXPath" value=".[pmd-java:hasAnnotation('org.springframework.boot.autoconfigure.SpringBootApplication')]" />
  </properties>
</rule>

PMD docs on violationSuppressXPath: https://pmd.github.io/pmd/pmd_userdocs_suppressing_warnings.html#the-property-violationsuppressxpath

Distend answered 5/7, 2024 at 8:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.