You can't change configuration 'providedRuntime' because it is already resolved - gradle

I am using Gradle 2.0 with Groovy 2.3.3.
When I run the build below I get the error > You can't change configuration 'providedRuntime' because it is already resolved!
Other posts and release notes suggest that it is to do with +=, however, I'm not using that operator so I am a bit confused.
apply plugin: 'war'
repositories {
mavenCentral()
}
//We don't want transitive dependencies added as we are matching a third-party build
configurations.all {
transitive = false
}
war {
archiveName='gradle.war'
from(configurations.providedRuntime.files) {
into "app-jars"
}
classpath fileTree('webinf-libs') // adds a file-set to the WEB-INF/lib dir.
}
dependencies {
providedRuntime group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.2'
}

Changing war configuration to:
war {
archiveName='gradle.war'
from(configurations.providedRuntime) {
into "app-jars"
}
classpath fileTree('webinf-libs') // adds a file-set to the WEB-INF/lib dir.
}
will solve the issue.
The problem occurred because files was called in war configuration block and then dependencies were added to providedRuntime. Since calling files resolves the configuration (and war block is evaluated at configuration phase) it can't be modified later on.
You can also change order of dependencies and war and it will be the same.

Related

Convert Maven `maven-assembly-plugin` to Gradle

I'm converting a Java project from Maven to Gradle.
One of the pom.xml is using maven-assembly-plugin to package dependencies into a single zip file.
I'm using custom configuration to specify the dependencies to package like so:
group = 'com.company'
description = 'projectA'
configurations {
ciPlugin
}
dependencies {
ciPlugin group: 'org.apache.httpcomponents', name: 'httpclient', version:'4.3.1'
}
jar {
into('plugins') {
from configurations.ciPlugin
}
}
This works almost fine beside the fact I have the following files in the resulting zip file:
commons-codec-1.10.jar
commons-logging-1.2.jar
httpclient-4.5.3.jar
httpcore-4.4.6.jar
and when Maven runs it only has httpclient-4.5.3.jar.
Just for clarification, I'm not really packaging httpclient, I'm packaging private artifact but the behavior is the same.
How can I get only the direct dependency without transient ones?
Add the following (e.g. after the dependencies block):
configurations.ciPlugin.transitive = false
This will turn off transitive dependencies for all artifacts in the ciPlugin configuration.

Gradle: how to exclude jar from an ear file?

I have a question regarding excluding a jar file from an ear artifact. My project has the following modules:
project
- ejb_module
- war_module
- ear_module
- other_module
In my ear_module/build.gradle :
dependencies {
deploy project(ejb_module)
earlib project(ejb_module)
deploy project(war_module)
earlib project(war_module)
}
The problem is how I exclude the jar artifact produced from the war_module.
The war_module produces both war and jar artifact. The reason I need the jar artifact is that my other_module depends on it.
A complicated factor is that the war_module has some dependencies that needs to go via earlib.
So my question is how I exclude the war_module.jar from the ear file? It is included both at root and in APP-INF/lib.
I presume in your war_module you are applying both war and java plugins to get a .war. and .jar artifacts ?
Try:
deploy project(path: 'war_module', configuration: 'archives')
earlib project(path: 'war_module', configuration: 'archives')
It should pick up a .war only because if look into the Gradle war plugin code you can see that it overrides the default output of the project, if java plugin was included.
Additionally, war plugin uses java plugin to compile your code under the hood.
You, of course, can simply exclude the artefact from the build by using
config (project){exclude module: 'name'}
but I think this is not the best you can do here.
Try looking into providedRuntime and runtimeOnly configurations depending on which version of Gradle do you use.
If the artefact is used for compilation then compileOnly etc.
This configuration used in dependecies{} will use the jar but will not be going to expose it anywhere else then it should not land in any artefact that you build and this is probably what would fit you the most in your case, but the question wasn't asking about this it's just an advice.
Assume your EAR contains an another existing jar, said xxx.yyy.zzz.jar.
In your ear project's build.gradle, add the following
ext.replacement = 'your.group:xxx.yyy.zzz:your.version'
configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
// remove to.be.excluded.jar
if (details.requested.group == 'your.group' &&
details.requested.name == 'to.be.excluded' &&
details.requested.version == 'your.version') {
details.useTarget replacement
}
}
}
}
This way, the to.be.excluded.jar will be replaced by xxx.yyy.zzz.jar, that virtually removes it from the EAR.

Gradle 2.12 - Injecting plugins into sub-projects fails

I have a standard Gradle setup with a root and sub-projects. In my root build.gradle, I would like to configure a plugin and inject it into some of the sub-projects, e.g:
project(':web-app'){
apply plugin: 'gwt'
buildscript {
repositories {
jcenter()
maven { url 'http://dl.bintray.com/steffenschaefer/maven'}
}
dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
}
}
gwt {
//Shared stuff goes in here ...
}
}
Unfortunately, I am getting:
A problem occurred evaluating root project 'XXXX'. Plugin with id
'gwt' not found.
What am I doing wrong? If I do the same in the sub-project(s) build.gradle, it works.
Bonus questions, if the above works at all:
How do I inject in several sub-projetcs? Seems like project(':a',':b'){...} does not work.
If the sub-project also has gwt{...} block, will it be merged with the stuff injected from the root? If so what takes precedence?
Thanks

How to remove a class from the classpath after Gradle build

I have a jar that I need to include in my dependencies...
compile files('WebContent/WEB-INF/lib/wls-api.jar')
There's a class inside that jar that is causing trouble that I want to not be on the classpath when I run my app after a gradle build.
How do I get rid of that class after doing a gradle build?
it's a bit trickier than it looks like at first blink; because you will modify the original input!
You should create a configuration for the your modified artifact (this is a proof of concept build.gradle snipplet):
apply plugin: 'java'
task filteredJar(type:Jar){
// you may use a remote artifact by configuring a separate configuration for it and using a jar from:
// configurations.theConfig.resolvedConfiguration.resolvedArtifacts
from zipTree('a.jar')
archiveName 'xx.jar'
// use standard Copy/Sync like filters here, for the example i used
include '**/Tool.class'
}
configurations {
z1
}
artifacts {
z1 filteredJar
}
dependencies {
compile project(path: getPath(), configuration: 'z1')
}
or..alternatively, and might be more preferably:
put this magic into some separate project which will repackage this jar into a usebale one.

How to generate a war file based on two subprojects

I have a project which is splitted into two subprojects.
/project
/sub-project-a (backend with JAVA source which is compiled into JAR file)
/sub-project-b (frontend sources which are compiled with grunt via gradle call)
build.gradle
settings.gradle (contains include 'sub-project-a', 'sub-project-b')
My Question is how can I create a War file with sub-projects and external lib dependencies? The following code snipped is my current build.gradle:
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile project(':sub-project-a')
compile project(':sub-project-b')
compile 'com.google.code.gson:gson:2.2.4'
}
task copy(type: Copy) {
from 'sub-project-a/build', 'sub-project-b/build'
into 'build'
}
build.dependsOn clean, copy
war {
archiveName 'project.war'
}
One detail is important. The java context listener (deep inside project code) work with compiled backend as jar file from WEB-INF/lib folder. This means that all class files can't be easily used from WEB-INF/classes folder.
As you can see I played with dependencies and a custom copy task. I'm not sure what is right gradle way. How should I do this?
SOLUTION
Define with war.from methode, where you get your static sources.
gradle docu
from(sourcePaths) -
Specifies source files or directories for a copy. The given paths are
evaluated as per Project.files().
My changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}
SOLUTION (for cleanly closing this question) shamefully taken from the question's originator ;-)
Define subproject dependencies with the "war.from" method, where you get your static sources.
gradle documentation excerpt: from(sourcePaths) - Specifies source files or directories
for a copy. The given paths are evaluated as per Project.files().
Ronny's changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}

Resources