Gradle: Set context root of web application - gradle

I have 2 Gradle projects, A is the root, and B is a subproject of A.
Project B generates a .war file, which is included in the .ear file, that project A generates.
I'd like to implement a general solution, where I can change the context root of project B.
Based on my research, I should call the ear.deploymentDescriptors.webModule(path, contextRoot) method, where path is the path of the artifact B in the ear.
How can I get the name of the artifact of B from project A, so that I have something to call the above mentioned method?
Is there a better way to set the context root?

Assume project A has a build.gradle and within ear, the below code can be solve this -
plugins {
id 'ear'
}
dependencies {
deploy project(path:':b', configuration: 'archives')
}
ear{
/* some basis configuration */
libDirName 'APP-INF/lib'
deploymentDescriptor {
/* Some basic attributes */
fileName = "application.xml"
version = "8"
def Set<Project> subProj = project.getSubprojects();
subProj.each{proj ->
if(proj.name.contains("B")){
webModule(proj.name + "-" + proj.version + ".war", "/"+ proj.name)
} //if close
}//each close
}//deploymentDescriptor close
}//ear close

Related

Passing a gradle task arguments in command line

I'm trying to find the best way to pass a gradle task arguments from the command line.
I have this task. I want to unpack solutions from student exercises and copy them into the right place in the project to evaulate them. I call this task like this:
> gradle swapSolution -Pstudent=MyStudent -Pexercise=ex05
One Problem i have with this while doing this in IntelliJ while having the Gradle plugin enabled is that i get this error message when build the project. What could be a solution to this?
A problem occurred evaluating root project 'kprog-2020-ws'.
> Could not get unknown property 'student' for root project 'kprog-2020-ws' of type org.gradle.api.Project.
This is the gradle task:
task swapSolution(type: Copy) {
new File("${rootDir}/Abgaben").eachDir { file ->
if (file.name.toString().matches("(.*)" + project.property("student") + "(.*)")) {
def exDir = new File("/src/main/java/prog/" + project.property("exercise"))
if (!exDir.exists()) {
delete exDir
}
new File(file.path).eachFile { zipSolution ->
//def zipFile = new File("./Abgaben/" + file.name.toString() + "/" + project.property("exercise") + "Solution.zip")
from zipTree(zipSolution)
into "/src/main/java/"
}
}
}
}
Do you have any suggestions to optimize this process?
-P denotes the Gradle Project Property. If you need to use project properties you can specify it as a system property in gradle.properties file in project root directory.
If your task is of type JavaExec you can use --args switch and pass it in Arguments text field of the Gradle Task Run Configuration togenther with the task name like swapSolution -args="-student=MyStudent -exercise=ex05". See also
https://stackoverflow.com/a/48370451/2000323

gradle script, What’s difference between direct dsl and called by a custom function of “apply from:”

First, there are some common scripts deployed in private maven repo:
http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle
http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle
In the target project, build.gradle
subprojects {
apply from: 'http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle'
apply from: 'http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle'
}
it's OK!
but,
ext.applyScript = { script, version ->
apply from: "http://domain/repo/com/d/build/script/${script}/${version}/${script}-${version}.gradle"
}
subprojects {
applyScript('java-project', '1.0')
applyScript('maven', '1.0')
}
it will fail, with message:
"Error:Cannot add task ':javadocJar' as a task with that name already exists."
task ':javadocJar' is defined in script 'java-project-1.0.gradle'
and we have several sub projects.
why ?
BTW: anyone can give me a lead of source location of "apply from:"?
It's hard to location it by myself.
The problem is that in the latte case you are applying the scripts multiple times to the same root project.
How is that possible? It is quite interesting and a little bit tricky:
you are defining applyScript as a Closure on the extension container ext of the current Gradle project,
generally the apply from: ... is handled as a method call apply(Map) on the org.gradle.api.plugins.PluginAware interface which is one of the super interfaces of the org.gradle.api.Project interface
this means every time you write apply ... you are calling the apply method on the current Gradle project (the one where the apply ... is specified)
as you defined the apply ... as part of the closure, the standard delegation applies
it is semantically the same as this.apply ...
this by default points to the enclosing class/object which is the root project (here it cannot be anything else)
So even if it looks like you are applying the 2 scripts to all the subprojects, you are actually applying the 2 scripts N times to the root project (N is the number of subprojects).
What you need to do is to change the delegate to the correct Project instance.:
you can do it very easily by adding one additional argument to the closure and explicitly calling the apply method on that argument:
ext.applyScript = { project, script, version ->
project.apply from: "..."
}
subprojects {
applyScript(it, 'java-project', '1.0')
applyScript(it, 'maven', '1.0')
}
or you can set the delegate explicitly:
ext.applyScript = { script, version ->
apply from: "..."
}
subprojects {
applyScript.resolveStrategy = Closure.DELEGATE_FIRST
applyScript.delegate = it
applyScript('java-project', '1.0')
applyScript('maven', '1.0')
}

Reading includes from idl file in custom task

I want to make my gradle build inteligent when building my model.
To acquire this I was planning to read schema files, acquire what is included and then build firstly included models (if they are not present).
I'm pretty new to Groovy and Gradle, so please that into account.
What I have:
build.gradle file on root directory, including n subdirectories (subprojects added to settings.gradle). I have only one gradle build file, because I defined tasks like:
subprojects {
task init
task includeDependencies(type: checkDependencies)
task build
task dist
(...)
}
I will return to checkDependencies shortly.
Schema files located externally, which I can see.
Each of them have from 0 to 3 lines of code, that say about dependencies and looks like that:
#include "ModelDir/ModelName.idl"
In my build.gradle I created task that should open, and read those dependencies, preferably return them:
class parsingIDL extends DefaultTask{
String idlFileName="*def file name*"
def regex = ~/#include .*\/(\w*).idl/
#Task Action
def checkDependencies(){
File idlFile= new File(idlFileName)
if(!idlFile.exists()){
logger.error("File not found)
} else {
idlFile.eachLine{ line ->
def dep = []
def matcher = regex.matcher(line)
(...)*
}
}
}
}
What should I have in (...)* to find all dependencies and how should I define, that for example
subprojectA::build.dependsOn([subprojectB::dist, subprojectC::dist])?
All I could find on internet created dep, that outputted given:
[]
[]
[modelName]
[]
[]
(...)

gradle use variables in sub project that are defined in child

Root project build.gradle
subprojects{
task setUpEnvironmentDirs()<<{
file("${distDir}").mkdirs()
// FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
project.tree.each {File currentFile ->
def fileName = "${currentFile.getName().split("\\.")[0]}"
def destinationFile = "${distDir}/${fileName}/"
file("${destinationFile}").mkdirs()
}
}
}
Sub project build.gradle
copyEnvironmentProperties{
FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
}
setUpEnvironmentDirs{
FileTree tree = fileTree(dir:'../../../pngcommon/config-tokens', include:"*.properties")
}
The file tree that is commented out in the root project is the variable I am attempting to move to the sub project because the directory path will be different in each sub project. I saw a similar post and set mine up similarly, but I keep getting an error.
gradle use variables in parent task that are defined in child
Error:
What went wrong:
A problem occurred evaluating root project 'services'.
Could not find property 'tree' on project ':service'.
You just need to comment in the code that declares the local variable, and use tree.each instead of project.tree.each. The relative paths will be resolved correctly.

How to call a task in another sub project build file with parameters

I'm working on creating a multi project build file using Gradle. Many sub projects need to execute a task which exists in another sub project by passing in certain parameters. How can this be achieved in Gradle?
for example :
root project
- project B : task X
- project A : task Y (param m, param n)
I need projectB.taskX to call projectA.taskY(m,n)
Update:
Sub-Project A has a task of type JavaExec which needs an input parameter to the location of the properties file
task generateCode(dependsOn:['classes','build'], type: JavaExec) {
main = 'jjrom.ObjectGen'
classpath = sourceSets.main.runtimeClasspath
args 'arg1', 'arg2', file(propertiesFilePath).path
}
Now, there are 10 sub projects, all of which need to call this task 'generateCode' with a parameter that contains the location to the properties file. Also, this task should be executed before building each sub-project which can be achieved using dependsOn.
My java project code organisation:
trunk/
projA/src/java/../ObjectGen.java
projB/src/java/../properties.xml
projC/src/java/../properties.xml
projD/src/java/../properties.xml
....
A task cannot call another task. Instead, the way to solve this problem is to add a generateCode task to all ten subprojects. You can do this from the root build script with code similar to the following:
subprojects {
apply plugin: 'java'
configurations {
codegen
}
dependencies {
// A contains the code for the code generator
codegen project(':A')
}
task generateCode(type: JavaExec) {
main = 'jjrom.ObjectGen'
classpath = configurations.codegen
args 'arg1', 'arg2'
}
compileJava.dependsOn(generateCode)
}
If there is no general pattern as to where the properties file is located, this information can be added in the subprojects' build scripts:
generateCode {
args file('relative/path/to/properties/file')
}

Resources