Groovy Unable to Load XML from Jar Resource


(Tim Razik) #1

I am attempting to write a small plugin wrapper for PMD. I would like to package our custum rules.xml into the the jar. I have a simple build.gradle

apply plugin: 'groovy'
apply plugin: 'java'

dependencies {
    compile gradleApi()
    compile localGroovy()
    compile files('pmd-core-5.2.3.jar')
    compile files('pmd-java-5.2.3.jar')
}

sourceSets {
        main {
                resources {
                        srcDirs "src/main"
                }
        }
}

I also have my plugin class

package com.aonhewitt.gradle.plugins

import org.gradle.api.*
import org.gradle.api.file.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.TaskExecutionException
import org.gradle.api.plugins.quality.PmdPlugin

class UPointPMDPlugin implements Plugin {

    /* This is the application of the Plugin
     * Project - the current project in which this plugin is running for.
     */
    void apply(Project curProject)  {
            curProject.plugins.apply(PmdPlugin)
            curProject.pmd {
                    rulePriority 2

                    // URL comes back with a valid value
                    URL url = getClass().getResource("/pmd-ruleset.xml")

                    // This fails to open the stream saying file not found
                    String text = url.getText()

                   //Added a test just to see if I could load a different file.  This worked
                   URL urlMan = getClass().getResource("/META-INF/MANIFEST.MF")
                   String manText = urlMan.getText()
             }
      }

}

I have placed my pmd-ruleset.xml in src/main/resources
The compiled jar has the xml file in the root of the jar

When I apply the plugin it correctly loads the manifest file but fails to load the resource file. I am thinking that something in the groovy class loader is not recognizing resources as being on the class path. As I mentioned the URL comes back valid as it is not null and it returns a fully qualified path. For some reason when calling getResourceAsStream, it cannot locate the file.

Failed to apply plugin [class ‘com.aonhewitt.gradle.plugins.UPointPMDPlugin’]
JAR entry pmdrules/pmd-ruleset.xml not found in /media/gradle_1/upoint/upf-trunk/trunk/ah-gradle-plugins.jar

Any suggestions on how to get the resources to be recognized at runtime?


(davidmichaelkarr) #2

I see a couple of odd things here.

You say you put “pmd-ruleset.xml” in “src/main/resources”. That directory is the default location for non-test resources, but you’re overriding that location with your sourceset declaration, so it will think your resources are in “src/main”. Then you say that the xml file is in the root of the jar, which seems hard to believe, from what I’m seeing here.

Then, you show the code that references “/pmd-ruleset.xml”, but the error message clearly says that it couldn’t find “pmdrules/pmd-ruleset.xml”.

Assuming you actually put the file in “src/main/resources”, I would first remove your sourcesets declaration. If you still have problems after that, show us what you’re actually getting, and make sure the code and facts match reality.


(Tim Razik) #3

Thakns for Replying David. I cleaned up some of the code. My apologies. I have been chaning the code so much bu trying various things, it got a bit confusing. I think I have made some progress.

I added that additional source set so that I could include the code in my jar for reference.
I did however remove that source set and tidied up the code.

So I have taken the following clean up steps
1: I moved my file to src/main/resources/pmdrules/ (I am going to add other rules like checksytles) so wanted to keep them separate

2: I updated the code to clear out extra print lines and such. Note this is Groovy.

class UPointPMDPlugin implements Plugin {
void apply(Project curProject) {.
curProject.plugins.apply(PmdPlugin)

                curProject.pmd {
                        rulePriority 2
                        curProject.pmd.toolVersion = '5.2.3'

                        URL url2  = getClass().getResource("/pmdrules/pmd-ruleset.xml")
                        String xmlFileRuleSet = url2.getText()
                        println xmlFileRuleSet
                        ruleSetConfig = curProject.resources.text.fromString(xmlFileRuleSet)
          }
        }
}

3: I removed the extra source set so we have one less wild card. So this is my build.gradle

apply plugin: 'groovy’
apply plugin: 'java’
apply plugin: “ivy-publish”

dependencies {
compile gradleApi()
compile localGroovy()
compile files(‘pmd-core-5.2.3.jar’)
compile files(‘pmd-java-5.2.3.jar’)
}

  1. I assemble the jar and verify that my resources are there. (Now that I have removed my sourceset, the groovy code is no longer in the jar, butthe .class files are still there)

  2. I use that jar as a dependency in my code build and in allProjects I apply UPointPMDPlugin

When I run ./gradlew task it now seems to work, but here is the odd thing. I ran it around 20
However after several runs I randomly get this error

A problem occurred evaluating root project ‘foundation’.
Failed to apply plugin [class ‘com.aonhewitt.gradle.plugins.UPointPMDPlugin’]
invalid stored block lengths

I have to run ./gradlew --stop then re-run my task

When I re-run the task, without changing anything, sometimes it works, and sometimes I get

Failed to apply plugin [class ‘com.aonhewitt.gradle.plugins.UPointPMDPlugin’]
JAR entry pmdrules/pmd-ruleset.xml not found in /media/gradle_1/upoint/upf-trunk/trunk/ah-gradle-plugins.jar

I’ll keep digging but what I tihnk is happening is related to the gradle daemon. Because I am changing the jar and then copying the jar to it’s permanent location, I think something is getting cached or mixed up in memory. I can’t explain it, but if I turn off the gralde daemon, I don’t seem to have a problem. I’m able to run the ./gradlew task dozens of times without issue.

Is it possible that the daemon is caching something? I am using gradle 2.11. I may upgrade to 2.13 or 2.14 in the near future.