Gradle configuration/dependency syntax - gradle

I am struggling to understand the gradle groovy syntax for dependencies and what is going on behind the scenes. As a starter I don't see what is exactly happening in this code snippet ....
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
}
What I (hope to) understand (please correct if I am wrong):
dependecies is a method of the org.gradle.api.Project interface /
org.gradle.api.internal.project.DefaultProject class which expects a
Closure to configure the dependencies of the project.
compile is a org.gradle.api.artifacts.Configuration which has been added by the org.gradle.api.plugins.JavaPlugin
What I don't understand:
What exactly is happening by specifying group: 'commons-collections', name: 'commons-collections', version: '3.2' ?
Does this invoke some magic method of the compile configuration object (if so, which one)?
Are group, name and version named parameters of a method call or are they method calls themselves?
Does this create a new org.gradle.api.artifacts.Dependency instance which is added to the compile configuration?

Gradle (like other tools built with Groovy) makes lots of use of methodMissing(...): http://www.groovy-lang.org/metaprogramming.html#_methodmissing
So what happens in the case of dependencies is that you invoke a method that does not exist. The method name is the name of the configuration, and its arguments are the dependency specification.
methodMissing(...) will be called and this will in turn call one of the add(...) methods of DependencyHandler: https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/dsl/DependencyHandler.html

Related

gradle, is there side effect with exclude on a transitive dependency

In an android lib (my_lib) which has dependency on other lib (other_lib), the other lib has dependency on okhttp:3.10.0.
Now my lib would like to use okhttp:4.9.3
the other_lib has
api "com.squareup.okhttp3:okhttp:3.10.0"
so my_lib changed from:
api "com.mobile.xxx:other_lib:2.0.0"
to:
implementation("com.mobile.xxx:other_lib:2.0.0") {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
api "com.squareup.okhttp3:okhttp:4.9.3"
so that my_lib will still use other_lib, but all okhttp will be from okhttp:4.9.3. And make it still transitive so that the client of my_lib will get okhttp:4.9.3.
Question:
does it need the exclude group: 'com.squareup.okhttp3', module: 'okhttp'? without it the okhttp will still be using okhttp:4.9.3 since it's the newer version specified in my_lib with the
api "com.squareup.okhttp3:okhttp:4.9.3"
What is the difference with/or without the exclude here?
with specifying a newer version of the dependency (here api "com.squareup.okhttp3:okhttp:4.9.3"), will it bring in some side effect to the other_lib at runtime? i.e. what if the other_lib is using some old interface/method within the okhttp:3.10.0 but that has been removed/altered in okhttp:4.9.3, will the other_lib still function correctly?

gradle default configuration, what is it and how can I define it

I am having a weird error, for which I found a lot of hits in google but most about android studio or library imports and I don't use android studio nor am I trying to build any app/library so I'll try and ask here and see if I understand the background of it.
I have a project in which I have this plugin:
https://gitlab.com/zkovari/gradle-mermaid-plugin/-/blob/master/examples/single-project/build.gradle
This is a plugin that displays my dependencies as a mermaid graph.
Everything was fine until today I updated some dependencies and created a sub-project to do something else.
I'm trying to generate the graph again and somehow it's failing with this error message.
> Task :generateMermaidDependenciesDiagram FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':generateMermaidDependenciesDiagram'.
> Configuration with name 'default' not found.
I can see in the source code of the plugin that it automatically sets some configurations
#Override
public void apply(Project project) {
GenerateMermaidDependenciesDiagram generateDependencyDiagramsTask = project.getTasks()
.create(GENERATE_MERMAID_DEPENDENCIES_DIAGRAM_TASK_NAME, GenerateMermaidDependenciesDiagram.class);
generateDependencyDiagramsTask.setConfiguration("default");
generateDependencyDiagramsTask
.setOutput(project.getBuildDir().toPath().resolve("mermaid/dependencies.mmd").toFile());
generateDependencyDiagramsTask.setDiagramGenerator(new MermaidDiagramGenerator());
}
So my question is a bit high level but what is the "default" configuration?
And in my project I don't really have any configuration block I simply have my dependencies:
dependencies {
implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: awsVersion, transitive: false
...
testCompile group: 'org.slf4j', name: 'slf4j-simple', version: slf4jVersion
}
My structure looks like this:
project:
-- build.gradle
-- settings.gradle
-- sub-project:
--- build.gradle
I think this stopped working when I added my sub-project but the plugin is applied at the root project level.
I do have a dependency between my sub-project and my root project (one of my sub-project tasks depends on the root project)
I'm trying to understand that this might be very similar but I'm not fully getting it.
Gradle: What Is The Default Configuration and How Do I Change It
I do apply the java plugin on my main project so I expect the configuration.default should exist.
Even if I think I shouldn't do it I tried to re-define a default configuration extending implementation but that did not work
https://docs.gradle.org/current/userguide/declaring_dependencies.html
configurations {
default.extendsFrom implementation
}
build file 'C:\dev\repo\connector-custom\build.gradle': 66: unexpected token: default # line 66, column 5.
default.extendsFrom implementation
I did a quick test and removing my subproject did work so I know the problem is there but no idea why.
It means somehow I must pass to my subproject the default configuration of the main project?

Liferay 7.2 No value has been specified for property 'apiDir'

I created a module project using servicebuild template (gradebook-api, gradebook-service), but i have an error after an export package com.liferay.training.gradebook.validator in api below
Bundle-Name: gradebook-api
Bundle-SymbolicName: com.liferay.training.gradebook.api
Bundle-Version: 1.0.0
Export-Package: \
com.liferay.training.gradebook.exception,\
com.liferay.training.gradebook.model,\
com.liferay.training.gradebook.service,\
com.liferay.training.gradebook.service.persistence,\
com.liferay.training.gradebook.validator
-check: EXPORTS
-includeresource: META-INF/service.xml=../gradebook-service/service.xml
i have a problem in the BuildService gradle task that's says :
Some problems were found with the configuration of task
':modules:gradebook:gradebook-api:buildService' (type
'BuildServiceTask').
File 'C:\Liferay\ide-workspace\training-workspace\modules\gradebook\gradebook-api\service.xml'
specified for property 'inputFile' does not exist.
No value has been specified for property 'apiDir'.
And this is a how I add the api module as dependency in service.
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.io"
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly group: "javax.portlet", name: "portlet-api"
compileOnly group: "javax.servlet", name: "javax.servlet-api"
compile project(":modules:gradebook:gradebook-api")
}
buildService {
apiDir = "../gradebook-api/src/main/java"
}
group = "com.liferay.training.gradebook"
I am trying to create new Liferay workspace but i got the same error (May be this is an error with Gradle)
Be sure, you run gradle task in the corresponding folder (in gradebook-service folder). I got similar error when I ran it in upper folder which contains api and service folder.
Until recently I have only worked on LR 7.0, but the last day or so have been playing with 7.3. I encountered the exact issue you describe.
The only solution I found was to copy service.xml from gradebook-service into the root of both my gradebook-api and gradebook-web modules and also add the following to the build.gradle files of both the gradebook-api and gradebook-web modules:
buildService {
apiDir = "../gradebook-api/src/main/java"
}
After that service builder ran successfully. There may be a cleaner way around it, but this worked for me.
service.xml should stay in service module only. Here, it look you need few checks.
api module dependency should be compileonly. not in compile
scope.
block order also matters in gradle file. move below block
at the top of the file.
buildService {
apiDir = "../gradebook-api/src/main/java"
}
not sure why you need -check:exports header in bnd file. As, that is not required normally.
In the Gradle task tab, go to your specific module service folder and then build it from there. Don't forget to refresh your gradle by pressing Cntrl+F5.
This Worked for me.
I had the same situation and just added the buildService{...} in build.gradle in the api module.
buildService {
apiDir = "../gradebook-api/src/main/java"
}
After: BUILD SUCCESSFUL

Spring boot, exclude dependencies from test in Gradle 5

I want to exclude two jars from test and only use them when the application is actually running.
dependencies {
runtimeOnly('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
runtimeOnly('org.springframework.cloud:spring-cloud-starter-config')
}
How do I explicitly tell Gradle 5 not to load these jars during the running of tests? I have already disabled their use but they keep getting loaded anyway. I was hoping for something simple like below, but I've been unable to find a conclusive answer.
test.exclude {
group 'org.springframework.cloud'
}
EDIT
Copy paste solution
configurations.testCompile.exclude(group: 'org.springframework.cloud', module: 'spring-cloud-starter-netflix-eureka-client')
configurations.testCompile.exclude(group: 'org.springframework.cloud', module: 'spring-cloud-starter-config')
Inside your dependencies block, you can do something like:
configurations.testCompile.exclude(group: 'the-group', module: 'the-module')
Hope this helps!

localGroovy method within plugin groovy code

In my plugins, I am always trying to add Groovy to Java. Now this code works just fine when in a build.gradle file, but when I move it to a plugin groovy file so I can compile it and distribute it, it says it can't find the method localGroovy(). What's the correct syntax to call the localGroovy() method here?
project.with {
plugins.withType(JavaPlugin) {
//noinspection GroovyAssignabilityCheck
configurations.all {
resolutionStrategy {
force localGroovy()
}
}
}
}
The method localGroovy() is defined in the DependencyHandler interface. I don't know where in your build script you were using the above code snippet, but you would need to be in the scope of a DependencyHandler to access this method. However, in your plugin, you could just use the DependencyHandler under projects.dependencies:
[...]
resolutionStrategy {
force project.dependencies.localGroovy()
}
[...]
Please note, that I did not test this code and it relies on your statement that the used method force(...) can handle whatever Dependency implementation is returned by localGroovy().
According to the docs, the force(...) method can handle the following inputs:
String in a format of: 'group:name:version', for example: 'org.gradle:gradle-core:1.0'
instance of ModuleVersionSelector
any collection or array of above will be automatically flattened
As long as the Dependency returned by localGroovy() implements the ModuleVersionsSelector interface (e.g. as ExternalDependency), the solution above should work like a charm.

Resources