I'm restructuring/refactoring build process for a big(ish) project. Currently it contains over a dozen separate modules built with standalone build scripts each. I want to integrate them all into a single multiproject build in Gradle.
After I integrated all sources into a single tree, fixed build.gradles, I came upon the following problem. Dependencies for many modules contain something like:
dependencies {
compile group: 'com.company', name: 'Module', version: '1.2.3'
// ...
testCompile group: 'com.company', name: 'Module', version: '1.2.3', classifier: 'tests'
}
I want the build to use jars from the subproject, not from a repository. I replaced compile ... with compile project(':Module') and it works fine. However, I cannot find the way to pass 'tests' specifier to the testCompile project... dependency.
Is there a way to pick up the tests jar as a dependency to testCompile?
In the producing project you will need to declare the "Test" JAR as outgoing artifact.
configurations {
testUtils
}
task testUtilsJar(type: Jar) {
...
}
artifacts {
testUtils testUtilsJar
}
In the consuming project you depend on it as such:
dependencies {
testCompile project(path: ':Module', configuration: 'testUtils')
}
Related
I am posting here to understand how does JHipster work with Gradle dependencies, in particular with regards to the fact that I am unable to copy some of them into a Gradle submodule I have created inside my JH project.
For example, the following doesn't work in a Gradle submodule
compile "junit:junit"
Error is
Could not resolve: junit:junit
However, the classic one copied from mvnrepository works great
compile group: 'junit', name: 'junit', version: '4.12'
Some additional information: I am creating a submodule that contains a set of classes related to testing, mainly a large load of custom Hamcrest matchers copied from another project from the Ant world. The original project had a lot of spaghetti code mess, so now I am refactoring into an isolated Gradle module. The testlib module shall depend on the testing frameworks and contain everything required for writing good tests. It can be compared to spring-test project you would use to write your own Spring-based tests.
At the moment, the gradle file looks like
plugins {
id "java"
}
configurations {
providedRuntime
implementation.exclude module: "spring-boot-starter-tomcat"
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
group 'org.example' //different from com.acme of super-project
version '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
dependencies {
compile group: 'org.assertj', name: 'assertj-core', version: '3.13.2'
compile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.2'
compile group: 'org.hamcrest', name: 'hamcrest', version: '2.1'
compile group: 'org.mockito', name: 'mockito-core', version: '3.0.0'
compile group: 'org.springframework.boot', name: 'spring-boot', version: spring_boot_version
compile "junit:junit" //Fails
}
Question
So the question is in two parts:
why does the scope "orgId:name" syntax work in the JHipster-generated module but not in submodules? Is it part of standard Gradle syntax?
why is that not working in a sub-module? Does JHipster apply a custom plugin to apply the correct version number that is clearly missing? How I do the same in a sub-module that is supposed to contain only Java library code?
With regards to JHipster, a little of more investigation helped. According to this answer, there is a trick in Gradle called Bill Of Materials project, so...
TL;DR
Add the following to the sub-project
// import JHipster dependencies BOM
implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")
So that the whole block looks like
dependencies {
// import JHipster dependencies BOM
implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")
compile "org.assertj:assertj-core"
compile "org.junit.jupiter:junit-jupiter-api"
compile "org.hamcrest:hamcrest"
compile "org.mockito:mockito-core"
compile "org.springframework.boot:spring-boot"
compile "junit:junit"
}
Long answer
Maybe in the future when I will understand Gradle more. Or just edit this answer 😁 to contribute
The bom defines the versions (besides other things) of 3rd party dependencies to be used so you can omit the explicit version. If you do not use the bom you can also write compile "junit:junit:4.12" but keep in mind jhipster uses already junit5 for all tests by default.
Regarding the import of the bom you can do it like you proposed or try to apply that dependency to all gradle subprojects in your main gradle file.
How can I save all the dependent jars for a module to a directory? I have an application that runs in IntelliJ IDEA, but I want to run it on another computer so I need to copy all the JAR files there.
Firstly, please consider using Gradle (or Gradle Wrapper) to do such things like getting/downloading dependencies of a project on another computer. But if you need to copy dependencies for any other reason you can define a task similar to:
task copyDependencies(type: Copy) {
from configurations.runtime
into "lib"
}
When you run:
gradle copyDependencies
runtime dependencies will be copied to a lib/ folder.
Example
build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.1'
compile group: 'com.h2database', name: 'h2', version: '1.4.196'
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
}
task copyDependencies(type: Copy) {
from configurations.runtime
into "lib"
}
Command:
gradle copyDependencies
And lib/ directory contains:
lib
├── groovy-all-2.3.11.jar
├── h2-1.4.196.jar
└── jackson-core-2.9.1.jar
Use Gradle Wrapper
As I mentioned earlier, please consider using Gradle Wrapper so you don't have to worry about if there is a Gradle distribution installed on another computer. As stated in the documentation you can easily add Gradle Wrapper and then you can run
./gradlew [task]
by using wrapper instead of Gradle installed on your OS. In your case running
./gradlew build
will download all dependencies and build the project. It's way better than copying dependencies manually, Gradle was invented to do it for us.
following solution worked for me
configurations.implementation.setCanBeResolved(true)
configurations.api.setCanBeResolved(true)
task copyDependencies(type: Copy) {
from configurations.implementation
into "libs"
}
Following the suggestion on this thread, I added the jars I wanted to reference in a folder named lib in the project root and I added the following gradle dependencies to my project:
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.cloud:spring-cloud-starter-eureka')
compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'org.apache.commons', name: 'commons-io', version: '1.3.2'
compile files('/lib/aspose-cells-17.02.0.jar');
compile files('/lib/bcprov-jdk16-146.jar');
}
Now, when I look at File -> Project Structure -> Modules -> Dependencies (tab) in IntelliJ, it shows every other dependency as having been added by Gradle except the two files I included above.
Is that the way it is supposed to appear? Have I done anything wrong? Or is there another way to make the word Gradle: appear in front of those dependencies?
The jar amazon-kinesis-connectors is using amazon-kinesis-client. I want to change this dependency to a local custom jar:
dependencies {
compile ('com.amazonaws:amazon-kinesis-connectors:1.2.0'){
exclude group: "com.amazonaws", module: "amazon-kinesis-client"
}
compile files('libs/amazon-kinesis-client-1.6.3.jar')
//...
}
It compiles ok, but when I'm running the code I get java.lang.NoClassDefFoundError: com/amazonaws/services/kinesis/clientlibrary/interfaces/IRecordProcessorFactory. Is there a way to do this dependency management in gradle?
As environment I'm using:
gradle 2.13
intellij idea CE 2006.1
java 1.8
Edit:
dependency graph in intellij:
Running using a gradle task:
task run_app(type:JavaExec) {
main = 'org.main.RunApp'
classpath = sourceSets.main.runtimeClasspath
}
try below gradle configuration
dependencies {
compile ('com.amazonaws:amazon-kinesis-connectors:1.2.0'){
exclude group: "com.amazonaws", module: "amazon-kinesis-client"
}
compile files('libs/amazon-kinesis-client-1.6.3.jar')
runtime files('libs/amazon-kinesis-client-1.6.3.jar')
//...
}
or you can use application plugin to create executable jar
https://docs.gradle.org/current/userguide/userguide_single.html#application_plugin
Say I have a project ProjectA with a compile dependency on core. And core depends on deepcore. Thus, ProjectA has a transitive dependency on deepcore.
So, build script for ProjectA has this
dependencies {
compile "com.something:core:1.0.0"
}
And build script for core has this
dependencies {
compile "com.something:deep-core:1.0.0"
}
Now, there is a class CoreService defined in both core and deepcore with the same package structure. And I am using that class from my ProjectA, which implementation will it use? How do configure my dependency so that I am using the version from core?
This should do what you are looking for.
dependencies {
compile "com.something:deep-core:1.0.0" {
exclude group: 'com.unwanted', module: 'unwanted'
}
}