java.lang.ClassNotFoundException when trying to run custom rule
A source code analyzer
Brought to you by:
adangel,
juansotuyo
I followed the documentation here: https://pmd.sourceforge.io/pmd-4.3/howtowritearule.html, but when I get to the "Run PMD using your new ruleset" section, my custom class cannot be found. One thing that isn't clear in the documentation is where I should be creating the rule and ruleset files. In a new directory at the root of the maven project I want to analyze? Somewhere in the
src/main/java
directory? In a completely different maven project? Does the answer change if I ultimately want to be running this rule as part of my maven build?The latter isn't even kind enough to throw a ClassNotFoundException... It seems to just skip over my rule and continue on its way:
Hi Jim,
please note, that the documentation you use, is very very old (version 4.3), PMD is now at version 6.9.0....
The latest documentation can be found via https://pmd.github.io , so e.g. https://pmd.github.io/pmd-6.9.0/pmd_userdocs_extending_writing_pmd_rules.html
Since you are using maven, that makes life much easier: I've prepare a sample project for creating a custom rule here: https://github.com/pmd/pmd-examples/tree/java
This also shows you, how to use the new rule for analyzing the project.
This is always a completely separate project. You have one project, that helps you building your main project (aka. "build-tools") and you have your main project, you want to analyze, where you use the build-tools-project. This build-tools-project contains the custom PMD enhancements as well as the ruleset.
Hope that helps,
Andreas
Thanks for the tips, and for putting together those examples... Forgive me if I'm slow but I'm not much of a maven expert. I put my custom rule and coresponding ruleset in their own project and built it into a jar. Then in my main project I added in the below to the pom.xml:
The dependency seems to get resolved ok, but the custom rule doesn't seem to be evaluated. Any sort of
mvn pmd:pmd
ormvn clean verify
or whatever else in the main project just results in this same dissapointing output:Any idea what I'm missing here? I revised my custom rule to just log something and add a violation, so it seems like it ought to be doing something.
Hi,
what you need to do is: use your custom rule in a custom ruleset and use this ruleset when executing pmd :)
So, you'll need to create a own ruleset and use this ruleset in the configuration of the maven-pmd-plugin via the
<rulesets>
tag.From the example:
Hi Andreas,
I appreciate you looking into this. Ultimately it just isn't working... I defined everything to match your project structure exactly, tried dozens of different ways of running it, and ultimately this just turned into a black hole. I still get
java.lang.ClassNotFoundException: com.driftt.rules.UnsecuredEndpointRule
when running via the CLI and no output when running viamvn pmd:pmd
no matter where/how I define and configure all this stuff. FWIW I really like PMD (used it effectively with Ant/Apex), but it's been far too hard to implement in a Maven/Java world, where I am admittedly less experienced. Ultimately I took 5 minutes to write this rule that I think would be useful (detects unauthenticated endpoints in Dropwizard resources), and a couple days later I still haven't been able to run it a single time.Last edit: Jim Madrigal 2018-11-25
Are you able to share your complete project? Especially the pom.xml filex are important...
If you run PMD from CLI, then you need to add your custom rule to the classpath so that PMD can see it. Maybe the example without maven is helpful there: https://github.com/pmd/pmd-examples/tree/java-without-maven - you can use the environment variable
CLASSPATH
to add additional jars to the runtime classpath of PMD (or just copy the jar file into the lib folder...).I decided to go ahead and try and get it working via the CLI, and was ultimately successful (adding the jar to the lib folder), which was pretty exciting. I'd still like to incorporate these checks into maven if possible, but unfortunately I can't share the full pom.xml in the service, but I'll post the build section I added. Here are the relevant snippets:
in the service
in the custom rule's project
Hi,
if your custom rule is not executed from within maven, then we'll need to have a closer look at the maven-pmd-plugin configuration:
Where is the file
ruleset.xml
exactly located? It should be in the project "pmd-rules" under the pathsrc/main/resources/ruleset.xml
, so that it is included in the pmd-rules-1.0-SNAPSHOT.jar.Also, please double check, that your new rule is included in this ruleset.xml.
Looks something like this:
I confirmed that the new rule is included in the ruleset.xml -- it is executed correctly when I specify the
pmd-rules/src/main/resources/ruleset.xml
as the ruleset in the CLI.apologies for the terrible formatting... hopefully it's at least clear :)
Last edit: Jim Madrigal 2018-11-26
Ok, so if you are building your main project, the maven-pmd-plugin will copy the ruleset(s) it is using into the target folder of each module. Could you have a look at
.../target/ruleset.xml
, whether this is the correct ruleset?The notation
<ruleset>ruleset.xml</ruleset>
could be ambigous. To avoid this, you could move the ruleset in the "pmd-rules" project into a subpackage, e.g. intopmd-rules/src/main/resources/com/driftt/ruleset.xml
and then use it in the main project like<ruleset>com/driftt/ruleset.xml</ruleset>
.I tried a few permutations of what you mentioned above but I'm not seeing any
ruleset.xml
in/target
. The generated target winds up looking like this after amvn clean install
:Searching through all these subdirectories still doesn't turn up a ruleset.xml anywhere.
the only mention of PMD in the output of the build is: