23

I'm using Gradle's Application plugin to generate the install for a standalone java application. I have a configuration file I need to put on the classpath but I can't seem to get it to generate the classpath correctly in the sh/bat files. This configuration file needs to be located outside of the jar.

The conf file is in the directory /src/dist/conf/ so when I run installApp it installs it under a conf directory like this $APP_HOME/conf.

I tried adding this directory to the claspath like this:

startScripts.classpath.add(files('$APP_HOME/conf'))

but when I look at the classpath in the sh/bat files it adds an entry that looks like this:

$APP_HOME/lib/conf

How do I tell gradle to drop the lib section for this entry?

Josh
  • 2,842
  • 8
  • 45
  • 51

6 Answers6

17

Another workaround for this issue (GRADLE-2333) is proposed by Alexandr Fadeev here.

Here is (a bit modified) Alexandr's solution that solved the problem for me on Gradle-1.6:

startScripts {
  classpath += files('src/dist/XxxAPlaceHolderForAConfigxxX')
  doLast {
    def windowsScriptFile = file getWindowsScript()
    def unixScriptFile    = file getUnixScript()
    windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\XxxAPlaceHolderForAConfigxxX', '%APP_HOME%\\config')
    unixScriptFile.text  = unixScriptFile.text.replace('$APP_HOME/lib/XxxAPlaceHolderForAConfigxxX', '$APP_HOME/config')
  }
}

It's a bit uglier than Josh's solution, but it allows you to preserve the exact directory layout (/src/dist/conf and $APP_HOME/conf) mentioned in the original question.

nehaev
  • 468
  • 4
  • 11
4

The easiest way to get a file onto the class path is to put it into src/main/resources. src/dist is for adding files to the distribution (i.e. zip file), not to the Jar/class path.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • 23
    Thanks @Peter Niederwieser, I would do that but I want this configuration file to be left outside of the jar. If it's in the src/main/resources it gets placed inside the jar. – Josh May 09 '12 at 15:48
4

This isn't a particularly good answer to your question, but I've found a few instances where the startScripts task doesn't quite yet have the flexibility we need.

I've worked around a couple of these instances by editing the file contents directly... not exactly taking advantage of Gradle's great model and not particularly recommended, but at least shows off how flexible Gradle is!

So you could hack something into the classpath like this:

tasks.startScripts {
  doLast {
    def scriptFile = file "${outputDir}/${applicationName}"
    scriptFile.text = scriptFile.text.replace('CLASSPATH=$APP_HOME/lib', 'CLASSPATH=$APP_HOME/conf/:$APP_HOME/lib')
  }
}

Be aware of breaking the start script's platform independence when doing this.

Martin Dow
  • 5,273
  • 4
  • 30
  • 43
3

It seems to me that what I'm trying to do shouldn't be that far out of the ordinary, but as a workaround I can have the dist directory be src/dist/lib/conf which allows the conf directory to be placed in the lib directory and the classpath that gradle generates for the sh/bat files to be correct.

I'll accept another answer if someone has a better one.

Josh
  • 2,842
  • 8
  • 45
  • 51
  • Thanks @Josh, but how do you use resources from `src/dist/lib/conf` when you run application form IDE? Because if you add them to `sourceSets.main.resources` they will appear in jar. – pgregory Aug 28 '14 at 12:01
  • 1
    @pgregory You can either add src/dist/lib/conf to the classpath within your IDE or also add the resources someplace like src/test/resources. I do the later because normally when I'm running things in the IDE it's tests and so it can share with the gradle test environment. – Josh Oct 21 '14 at 12:42
3

I did a variant of Martin Dow's recipe below:

I replace 'APP_HOME=' with 'export APP_HOME=' in the start script.

Then my code can do System.env.get("APP_HOME") and then navigate to e.g. the conf/ folder.

This is my Gradle hack:

tasks.startScripts {
  doLast {
    def scriptFile = file "${outputDir}/${applicationName}"
    scriptFile.text = scriptFile.text.replaceAll('APP_HOME=',  'export APP_HOME=')
  }
}

Example of Java code in the app:

String APP_HOME = System.env().get("APP_HOME");
Properties p = new Properties();
p.load(new FileInputStream(APP_HOME + "/conf/myapp.properties"))

Hope this helps.

NOTE: "export" does not work in Windows!

Olle Hallin
  • 588
  • 1
  • 3
  • 12
0

add the line inside build.gradle dependencies

runtimeOnly files('lib/config')

This will add lib/config into classpath list. Please note am using gradle 7

Riju Jacob
  • 1
  • 1
  • 2