How to refer to resources folder in debug mode? - gradle

I want to debug my web application in Jetty using gradle. I have some of my property files in source code. Since these files are not copied to WAR, I used the below code to use resources folder,
sourceSets.main.resources {
srcDirs = ["src/main/java"]; include "**/*.*"
}
This includes properties files in WAR. But when I debug in eclipse, it points to classes folder which doesnot contain properties folder. How to make debug to point to resources folder?
Build.gradle:
war {
doFirst {
def propertyFile = file "src/main/java/com/properties/about/About.properties"
def props = new Properties()
propertyFile.withReader { props.load(it) }
println "Before setProperty:"
println props.getProperty('releaseDate')
props.setProperty('releaseDate', new Date().format('yyyy-MM-dd-HH:mm:ss'))
propertyFile.withWriter { props.store(it, null) }
println "After setProperty:"
println props.getProperty('releaseDate')
}
buildDir = new File(rootProject.projectDir, "gradleBuild/" + project.name)
}

I solved this by creating src/main/resources folder and included all files other than class files in it. Say, I created properties\sample.properties and referred this path in code. Now there occurs no issue while debugging and also when deployed as WAR. By having resources folder all the files are included in WAR without having to modify build.gradle

Related

Gradle processResources expand on different projects modules

i'm trying to get a project.version so i wrote project2 gradle before codes
processResources {
def props = ['version': project.properties.get('version')]
filesMatching("**/MyConfiguration.kt") {
expand(props)
}
}
the MyConfiguration.kt file located project1 but the code return null
so i fixed codes like below
processResources {
def props = ['version': project.properties.get('version')]
expand(props)
}
then that codes return right value
maybe the problem is filesMatching input another module file?
i missed filesMatching input
need to setup .properties or .yaml (get project.properties this scope)

Download Gradle dependencies with ".modules" files

I currently have an offline environment where I have all my dependencies (jar, aar & pom files). The thing is that I want to use Coil (image library) as a dependency in my Android project. This library requires kotlinx-coroutines-core to be also downloaded in my environment. I have been able to download all the required files except for .module file (Gradle Module Metadata), which is necessary because there are multiple variants of kotlinx-coroutines-core (versions for the JVM, JS and Native).
In other words, my code downloads kotlinx-coroutines-core-jvm-1.3.9.jar (with its POM) and kotlinx-coroutines-core-1.3.9.pom which is great but kotlinx-coroutines-core-1.3.9.module file is still missing and not sure how can I download it.
Here is my code based on this gist:
task copyDependencies() {
def name = "default"
def configuration = configurations.getByName(name)
copyJars(configuration)
copyPoms(configuration)
}
private void copyJars(Configuration configuration) {
File repoDir = new File(project.buildDir, 'repository')
configuration.resolvedConfiguration.resolvedArtifacts.each { artifact ->
def moduleVersionId = artifact.moduleVersion.id
File moduleDir = new File(repoDir, "${moduleVersionId.group.replace('.', '/')}/${moduleVersionId.name}/${moduleVersionId.version}")
GFileUtils.mkdirs(moduleDir)
GFileUtils.copyFile(artifact.file, new File(moduleDir, artifact.file.name))
}
}
private void copyPoms(Configuration configuration) {
def componentIds = configuration.incoming.resolutionResult.allDependencies.collect { it.selected.id }
def result = project.dependencies.createArtifactResolutionQuery()
.forComponents(componentIds)
.withArtifacts(MavenModule, MavenPomArtifact)
.execute()
for (component in result.resolvedComponents) {
def componentId = component.id
if (componentId instanceof ModuleComponentIdentifier) {
File repoDir = new File(project.buildDir, 'repository')
File moduleDir = new File(repoDir, "${componentId.group.replace('.', '/')}/${componentId.module}/${componentId.version}")
GFileUtils.mkdirs(moduleDir)
File pomFile = component.getArtifacts(MavenPomArtifact)[0].file
GFileUtils.copyFile(pomFile, new File(moduleDir, pomFile.name))
}
}
}
So my question is: How can I download .module files when downloading my dependencies? An example would be downloading this file.
To copy a configuration's files to a directory, you can do this:
task copyLibs(type: Copy) {
from configurations.runtimeClasspath
into file("$buildDir/repository")
}
This will copy everything including transitive dependencies.
Not need to write all that code yourself. Why do you want POMs and all that in your application's classpath? Just let Gradle sort it out for you.

In a custom task in my buildSrc folder: How do I determine the file path of the subproject it is called in?

If I define a custom gradle task in buildSrc: How do I find out the relative path to the project from which the task is called?
In my buildSrc folder, I have a custom task that creates a Enum our of my message.properties file:
open class GenerateEnumTask : DefaultTask() {
#get:Input
open var inputFolder: String = "src/main/resources"
#get:Input
open val targetFilePath: String = "src/generated/kotlin/MessageCode.kt"
#get:OutputFile
val enumFile = File(targetFilePath)
#TaskAction
fun generateEnum() {
...
}
#Internal
override fun getDescription() = "This task uses downloaded property files and creates an enum kotlin file"
}
I then want to make sure the enum is generated before code compilation.
So I put this in the subproject "core", where I need the Enum.
build.gradle.kts:
tasks {
val generateEnumTask by registering(GenerateEnumTask::class)
withType<KotlinCompile> {
kotlinOptions.jvmTarget = Versions.jvmTarget
dependsOn(generateEnumTask)
dependsOn(formatKotlin)
doFirst{
println("compile kotlin in core project")
}
}
}
This does indeed work if I run gradle compileKotlin directly from the subfolder of the core project.
However, if I run the same command from the root project, the code searches for a src folder in the root directory.
Ah, the answer was simple: DefaultTask inherits from AbstractTask, which has a reference to the project that the task was called in (getProject)
This works nicely:
open var targetFolder: String = this.project.file("src/main/resources").absolutePath

Gradle doFirst not updating WAR file

In a gradle project, I'm trying to change properties file value before generating WAR in build.gradle as follows,
war {
doFirst {
def propertyFile = file "src/main/resources/properties/about/About.properties"
def props = new Properties()
propertyFile.withReader { props.load(it) }
props.setProperty('releaseDate', new Date().format("yyyy-MM-dd HH:mm:ss"))
propertyFile.withWriter { props.store(it, null) }
}
rootSpec.exclude("**/test.jar")
}
But whenever I give build, it generates WAR with previous date time. Say, I'm giving first build at 11:30 and second build at 11:34. The second built WAR contains time as 11:30 instead of 11:34. My intention is to update date whenever WAR is built. Is this way right?
I simplified your solution and tested it. For me it always updates the date in the properties file when i run build or just war. Be aware that i changed the path for test purposes. Here is the code:
war {
doFirst {
File propsFile = file "src/main/resources/about.properties"
Properties props = new Properties()
props.load(propsFile.newDataInputStream())
props.setProperty('releaseDate', new Date().format('yyyy-MM-dd HH:mm:ss'))
props.store(propsFile.newWriter(), null)
}
}
Keep in mind that the releaseDate of the about.properties is not included into the current war you are currently building since resources for the war you are packing had been processed before you execute war.
If you want to include the about.properties file with the time of the current build into the war archive, you should create a custom task to update your properties file and hook the task to a point into the buildchain before resources are processed. I created a sample task for you:
task updateReleaseDate {
doLast {
File propsFile = file "src/main/resources/about.properties"
Properties props = new Properties()
props.load(propsFile.newDataInputStream())
props.setProperty('releaseDate', new Date().format('yyyy-MM-dd HH:mm:ss'))
props.store(propsFile.newWriter(), null)
}
}
processResources.dependsOn updateReleaseDate
Without the custom task your buildchain looks like this. The properties are updated after the resources are processed by the processResources task and therefore not included in the current war: compileJava->processResources->classes->war
With the custom task your buildchain looks like this. The properties are updated before the resources are processed by the processResources task and therefore included in the current war: compileJava->updateReleaseDate->processResources->classes->war

Gradle task to load files from Jar

I use vendor library to generate Java sources from an Xml. This source xml imports other xml which exists in some jar file. I know the coordinates of this Jar file. The vendor library is a blackbox to me but I know that it uses ThreadContextClassLoader to load the imports from a jar. However, it fails because it cannot find the imported xmls from the classpath/jars.
What is the gradle way of accomplishing this?
// body of gradle task
#TaskInput
void execute(IncrementalTaskInputs inputs) {
inputs.outOfDate { changes ->
// CodeGenerator is the vendor library
CodeGenerator generator = new CodeGenerator();
// call some setter methods to set the inputs.
//
generators.setXml(file("<path/to/the-file"))
generator.generate();
}
}
From my other answer we have ascertained that there's no option to set the classloader for the CodeGenerator. So, the only option is to have the jar with the xml files loaded by the same classloader as the CodeGenerator`.
Option 1: Add the jar to the buildscript classpath in a buildscript { ... } block
buildscript {
dependencies {
classpath 'com.group:jar-with-xmls:1.0'
}
}
Option 2: Add the jar to the buildscript classpath via buildSrc/build.gradle
dependencies {
compile 'com.vendor:code-generator:1.0'
runtime 'com.group:jar-with-xmls:1.0'
}
Does the CodeGenerator have a setClassloader(Classloader) method? You could likely use a Configuration and a URLClassloader. Eg:
configurations {
codeGenerator
}
dependencies {
codeGenerator 'foo:bar:1.0'
codeGenerator 'baz:biff:2.0'
}
task generateCode {
inputs.files configurations.codeGenerator
outputs.dir "$buildDir/codeGenerator"
doLast {
URL[] urls = configurations.codeGenerator.files.collect { it.toUri().toUrl() }
Classloader cl = new URLClassLoader(urls, null)
CodeGenerator generator = new CodeGenerator()
generator.setClassLoader(cl)
...
generator.generateTo("$buildDir/codeGenerator")
}
}
See a similar concept here
jar files are zip archives. You can open them as zipfiles using java.util.zip classes. In gradle, you might want to use ziptree to extract, as explained here:
http://mrhaki.blogspot.jp/2012/06/gradle-goodness-unpacking-archive.html

Resources