In a simple gradle project I have under the projects root a config folder with a config.json in it. I want to put this file on the path to read it.
def myconfigfile = new File("config", "config.json")
def configset = files(myconfigfile)
task runExample ( dependsOn: 'classes', type: JavaExec ) {
main = 'com.example.LoadConfigExample'
classpath = sourceSets.main.runtimeClasspath
classpath.add(configset)
args 'ARG1'
}
In the Java file I'm using the following to load the file:
URL u = LoadConfigExample.class.getResource("config.json");
Would it be better just to use relative paths and load via the file system? I don't want to put the file under src/main/resources.
If I understood well the best option seems to refer to the config.json via project.file method, for docs see here.
It will be:
project.file("confif${File.separator}config.json")
Related
In build.gradle it is simple enough:
println "project name $name"
... but that wouldn't be available with a distributed version of the app. Nor do I understand how I can easily access that value from inside testing and app code.
The name should be available in "settings.gradle": hopefully this should contain a line like:
rootProject.name = 'MyProject'
If I want to incorporate this name into a test, and also into app code, and also to make sure that that info is available to a distributed version of the app, using installDist for example, it seems to me that the best way might be to automate, prior to testing, building and distributing, a task which extracts that information from settings.gradle and puts it into a .properties file under src/main/resources.
How would I do that? Or... is there a better approach?
PS a possible use case might be for configuring the path of a logfile: .../logging/MyProject... There are probably others.
build.gradle:
task copySettingsGradle {
doFirst {
ant.copy(file: 'settings.gradle',
todir: 'src/main/resources',
overwrite: true,
failonerror: true)
}
}
classes.dependsOn copySettingsGradle
app code:
URL settingsGradleURL = App.class.getResource( '/settings.gradle' )
ConfigObject conf = new ConfigSlurper().parse( settingsGradleURL )
def projectName = conf.rootProject.name
... the point about this being that it works both during Gradle development and in the distributed app...
I have the following scenario in my Android project:
Project1 --> Build.gradle (1)
Project2--> Build.gradle (2)
Example: Define the following variable:
//first Gradle file
def getProductFlavor() {
//Logic here
Gradle gradle = getGradle()
String requestingTask = gradle.getStartParameter().getTaskRequests().toString()
return requestingTask
}
Instead of defining getCurrentTime() in the second Gradle file,
I call the getCurrentTime() from the first Gradle file.
Maybe my example is wrong and the default value needs to be implementing in another gradle file like the script gradle or somewhere else, but the intent of the example was to clarify what I'm trying to achieve.
The two projects are independents but both belong to the same android project. I want to use ONE def value in both of these gradle files.
I'm a gradle newbie by the way. Never mind if I'm asking this question the wrong way.
Feels like a scenario for external script:
main-project
....| sub-project1
........| src
........| build.gradle
....| sub-project2
........| src
........| build.gradle
....| common.gradle
build.gradle
apply from: '../common.gradle'
def flavor = getProductFlavor()
common.gradle
def getProductFlavor() {
Gradle gradle = getGradle()
String requestingTask = gradle.getStartParameter().getTaskRequests().toString()
return requestingTask
}
ext {
getProductFlavor = this.&getProductFlavor
}
I have a gradle application with a structure like this
src\main\
antlr\
groovy\
jvm\
script.groovy
java\
resources\
program.pas
In my script I have a line
CharStream input = new ANTLRFileStream("program.pas")
I run script using this task
task runScript(dependsOn: 'classes', type: JavaExec) {
main = 'jvm.script'
classpath = sourceSets.main.runtimeClasspath
}
But when I do that I get FileNotFound exception for program.pas.
When I move to the root of the project - it is able to find it.
My built structure looks like this
build\
classes\
main\
jvm\
script.class
resources\
main\
program.pas
Why it is unable to locate in resources?
I am setting up a build pipeline for a spring boot project.
It has three stages so far:
build: compile-->unit test-->archive the jar
deploy acceptance test: repack the jar for acc environment (replacing datasource.properties etc)
deploy uat test: repack the jar for uat environment (replacing datasource.properties etc)
I don't want to build the jar from scratch for different environments as it wastes time and potentially has risk of building inconsistent artifacts.
For traditional war project, I just extract the war, replace the config files and repack. But this time with spring boot, somehow it does not work. When I run the repacked jar, it reports
java.lang.IllegalStateException: Unable to open nested entry 'lib/antlr-2.7.7.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:378)
at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:355)
at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:341)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:108)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:92)
at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:68)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:60)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:45)
I extracted the origin jar and the repacked jar and don't find differences with lib folder.
task extractArtifact() {
doLast {
def outputDirName = "${buildDir}/tmp/under_config"
def outputDir = file(outputDirName)
assert outputDir.deleteDir() // cleanup workspace
def zipFile = file("${buildDir}/libs/${getArtifactName()}")
copy {
from zipTree(zipFile)
into outputDir
}
copy {
from file("${buildDir}/env")
into file("${buildDir}/tmp/under_config")
}
}
}
task repackConfiguredArtifact(type: Zip, dependsOn: extractArtifact) {
archiveName = "${getArtifactName()}"
destinationDir = file("${buildDir}/libs/${getEnv()}")
from file("${buildDir}/tmp/under_config")
}
Does anyone have an idea?
Or how do you guys config the jar for different environment (without re-compile the binary).
You shoud add -0 to store only; use no ZIP compression
$jar -cvf0m yourproject.jar META-INF/MANIFEST.MF .
There is another soulution:
Set the active Spring profiles
$java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
You can use application-${profile}.properties to specify profile-specific values.
I have a solution after looking up the spring-boot reference.
turn default spring boot repackage off since I need to repack it anyway.
extract the traditional jar and copy the config files
Use jar type task to repack it
Use BootRepackage type task to assemble a spring-boot jar.
here is the code:
bootRepackage {
enabled = false
}
task extractArtifact() {
doLast {
def outputDirName = "${buildDir}/tmp/under_config"
def outputDir = file(outputDirName)
assert outputDir.deleteDir() // cleanup workspace
def zipFile = file("${buildDir}/libs/${getArtifactName()}")
copy {
from zipTree(zipFile)
into outputDir
}
copy {
from file("${buildDir}/env")
into file("${buildDir}/tmp/under_config")
}
assert zipFile.delete()
}
}
task clientJar(type: Jar, dependsOn: extractArtifact) {
archiveName = "${getArtifactName()}"
from file("${buildDir}/tmp/under_config")
}
task repackConfiguredArtifact(type: BootRepackage, dependsOn: clientJar) {
withJarTask = clientJar
}
I found that if you had a directory called 'resources/lib' the spring-boot executable JAR would assume the contents were zipped and throw the above exception. Renaming to 'resources/static' worked for me.
I ran across the following configuration in a Gradle project's buildfile (build.gradle):
codenarcMain {
configFile = rootProject.file("gradle/codenarc/CodeNarcMain.groovy")
}
When I Google "Gradle rootProject" I find this link which makes it look like rootProject is a ProjectDescriptor instance.
But looking at ProjectDescriptor, I don't see any property called file. I see a buildFile and projectDir, but no file property.
Ultimately, I am trying to get Gradle to load the CodeNarc config file from outside the build directory. On my system I have an env var called $CODENARC_HOME with the following directory structure:
CODENARC_HOME/ (say this is /home/myuser/tools/codenarc/)
CodeNarcMain.groovy
CodeNarcTest.groovy
README.md
Now I would like to change the CodeNarc config in Gradle to look something like this:
codenarcMain {
configFile = rootProject.file("CODENARC_HOME/CodeNarcMain.groovy")
}
And then, no matter where CODENARC_HOME is defined, the Gradle build will still be able to locate the config file.
So my questions:
What is the file property on rootProject, and why don't I see it in the API docs (linked above)?; and
How to get rootProject.file(...) to honor system/env vars inside its file path string argument?
rootProject in settings.gradle is-a ProjectDescriptor. rootProject in build.gradle is-a Project. Environment variables and system properties can be accessed in the standard Java way:
codenarcMain {
configFile = rootProject.file("${System.getenv("CODENARC_HOME")}/CodeNarcMain.groovy")
// or: System.getProperty("codenarc.home")
}