Fred Toth
Fred Toth

Reputation: 233

Gradle dependency destination on non-jar config file

I can create a dependency to something other than a jar file like this:

dependencies {
    compile files("../other-project/config.txt")
}

The above works fine, except that config.txt ends up in the WEB-INF/lib folder of my war file. Instead I need it to be in WEB-INF/classes in the war file, and in src/main/resources for jettyRun.

How can I control where the dependency ends up? Or am I going about this the wrong way?

I can also solve this with a copy task, but this really is a dependency in that I don't need the file updated unless it changes. An unconditional copy would work, but I'd rather do this the right way.

Upvotes: 3

Views: 1551

Answers (3)

Fred Toth
Fred Toth

Reputation: 233

As I mentioned above, it's simple enough to do an unconditional copy that solves the problem. Again, not the question I originally asked. But here's my solution that works for both war and jettyRun tasks:

processResources.doFirst {
    copy {
        from '../other-project/config.txt'
        into 'src/main/resources'
    }
}

Upvotes: 0

Gerhard Schlager
Gerhard Schlager

Reputation: 3155

Let's say you have configured a multi-project build with the following directory and file structure:

/combined-war
    /main-project
        /src
            /webapp
                /WEB-INF
                    web.xml
        build.gradle
    /other-project
        /resources
            /WEB-INF
                /classes
                    config.txt
        build.gradle
    build.gradle

In order to allow jettyRun to combine the contents of the webapp directory from main-project with the contents of the resources directory in other-project you need to add a workaround to your build.gradle of main-project (I've adapted the one posted by the user siasia on gist).

Adding the same directory content to the war file is quite simple and is documented in the Gradle User Guide and and the DSL reference.

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'jetty'

import org.gradle.api.plugins.jetty.internal.JettyPluginWebAppContext

def newResourceCollection(File... resources) {
    def script = '''
        import org.mortbay.resource.ResourceCollection
        new ResourceCollection(resources)
    '''

    def shell = new GroovyShell(JettyPluginWebAppContext.class.classLoader)
    shell.setProperty("resources", resources as String[])
    return shell.evaluate(script)
}

jettyRun.doFirst {
    jettyRun.webAppConfig = new JettyPluginWebAppContext()
    jettyRun.webAppConfig.baseResource = newResourceCollection(
        // list the folders that should be combined
        file(webAppDirName),
        file("${project(':other-project').projectDir}/resources")
    )
}

war {
    from("${project(':other-project').projectDir}/resources")
}

Whenever you execute gradle jettyRun a new ResourceCollection is created that combines the given directories. Per default Jetty locks (at least on Windows) all the files it's serving. So, in case you want to edit those files while Jetty is running take a look at the following solutions.

Update

Since other-project in this case is not another Gradle project the two tasks in build.gradle should look like that:

jettyRun.doFirst {
    jettyRun.webAppConfig = new JettyPluginWebAppContext()
    jettyRun.webAppConfig.baseResource = newResourceCollection(
        file(webAppDirName),
        file("$projectDir/../other-project/resources")
    )
}

war {
    from("$projectDir/../other-project/resources")
}

I'm not aware of any solution that adds only one file (e.g. config.txt). You'll always have to add a complete directory.

Upvotes: 1

Peter Niederwieser
Peter Niederwieser

Reputation: 123960

The war task (as configured by the war plugin) puts dependencies into WEB-INF/lib, the web project's own code/resources into WEB-INF/classes, and web app content (which by default goes into src/main/webapp) into WEB-INF. Other content can be added by explicitly configuring the war task. For example:

war {
    into("WEB-INF/classes") {
        from "../other-project/config.txt"
    }
}

One way to make this work with embedded Jetty (though maybe not the most convenient during development) is to use jettyRunWar instead of jettyRun. Another solution that comes to mind, particularly if the content to be added resides in its own directory, is to declare that directory as an additional resource directory of the web project (sourceSets.main.resources.srcDir "../other-project/someResourceDir"). This is in fact an alternative to configuring the war task. If the web project already has a dependency on the other project, you could instead configure an additional resource directory for that project.

Upvotes: 1

Related Questions