Gradle to add module dependency in Micronaut project - java

I have three module as shown below
The fete-bird-apigateway depend on common and fete-bird-product depend on both fete-bird-apigateway and common
In the fete-bird-product settings.gradle I have included the code below
rootProject.name = "fete-bird-product"
include 'fete-bird-apigateway' , 'common'
and in the build.gradle of project
dependencies {
implementation project(':common')
}
Error
Caused by: org.gradle.internal.component.NoMatchingConfigurationSelectionException: No matching configuration of project :common was found.
I don't want to create a multi-module build project describe here https://docs.gradle.org/current/userguide/multi_project_builds.html. Each project should build individually and dependent modules should load while building.
How can I achieve this?

Well I found that I had the wrong concept for different module projects.
Assuming all modules are part of the same multi-module build then in fete-bird-apigateway.gradle and service\build.gradle you add:
plugins {
id 'java'
id 'maven-publish'
}
dependencies {
implementation project(':common')
}
However if common, fete-bird-apigateway and service are separate projects and don't share the same root build.gradle you have to publish the common module into a shared repository and use it like any regular dependency. Easiest to do with Maven Local repository.
To publish to the local maven
In fete-bird-apigateway.gradle
publishing {
publications {
maven(MavenPublication) {
groupId = 'org.gradle.sample'
artifactId = 'library'
version = '1.1'
from components.java
}
}
}
Reference - https://docs.gradle.org/current/userguide/declaring_repositories.html
https://docs.gradle.org/current/userguide/publishing_maven.html#gsc.tab=0
In the dependent project add the dependency as regular
repositories {
mavenLocal()
}
implementation("fete.bird:fete-bird-apigateway:0.1")
We need to run the task or gradle command for publish. I am using Intellj so did with below task
We can run the gradle command gradle publishToMavenLocal

Related

Build with gradlew and make it available in ./m2 [duplicate]

I have 2 different project build on mvn. I am trying to replace to Gradle.
Project 1 is an SDK, and project 2 is using that sdk (example).
In the time of maven it creates artifact using mvn install which adds the whole project into local repository.
I like to work in gradle like that. I like project 1 build.gradle need to post it as a gradle local repository and then example project need to use it.
In maven we do mvn install which adds a project artifact into .m2 folder but how to do in gradle so what i can add a project artefact's into the local repository.
Any way that I can do so?
sdk/build.gradle:
apply plugin: "maven"
group = "foo"
version = "1.0"
example/build.gradle:
repositories {
mavenLocal()
}
dependencies {
compile "foo:sdk:1.0"
}
$sdk> gradle install
$example> gradle build
You may be looking for:
gradle publishToMavenLocal
build.gradle:
plugins {
// other plugins
id 'maven-publish'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}
See: Maven Publish Plugin
Check out Gradle's documentation on multi-project builds.
Here's an example, with some extra dependencies. Just call gradle install in the root folder, and all will be built and put to your local repo.
Folder structure:
root
+--> build.gradle
+--> settings.gradle
+--> sdk
| +--> build.gradle
+--> example
+--> build.gradle
root/build.gradle:
allprojects {
apply plugin: 'java'
apply plugin: 'maven'
group = 'myGroup'
version = '0.1-SNAPSHOT'
}
root/settings.gradle:
include 'sdk'
include 'example'
root/sdk/build.gradle:
dependencies {
// just an example external dep.
compile group:'commons-lang', name:'commons-lang', version:'2.3'
}
root/example/build.gradle:
dependencies {
compile project(':sdk')
compile group:'log4j', name:'log4j', version:'1.2.16'
}
You need to publish your own library to your local repository. You can do that in the following way:
Add maven-publish plugin:
plugins {
// your other plugins come here...
id 'maven-publish'
}
Add the publishing section to your build file:
publishing {
publications {
myCoolLibrary(MavenPublication) {
from components.java
}
}
}
Run gradle build publishToMavenLocal
Find more details in the documentation.

How to generate all-projects-in-one Gradle project?

I have a gradle monolithic project with too many dependencies.
I'd like to explode it into many sub-projects and publish all sub-projects (build + sources + javadoc) + an extra project being the merge of all sub-projects.
This extra project should be like a virtual artifact with all my projects in a single jar like it is today because I don't want a too big change for my users.
The jar must not include dependencies (it is not an uber-jar) but the resulted pom.xml must contain the dependencies of all sub-projects (the generated pom.xml of the maven artifact must contain all dependencies).
The virtual artifact will include the merge of javadoc and sources too in order to respect Maven Central conventions.
Current state:
Project Main, generate
pom.xml
main.jar
main-sources.jar
main-javadoc.jar
Expected state:
Subproject A, generate
A-pom.xml
A.jar
A-sources.jar
A-javadoc.jar
Subproject B, generate
B-pom.xml
B.jar
B-sources.jar
B-javadoc.jar
virtal-Project Main, generate
pom.xml=A-pom.xml+B-pom.xml
main.jar=A.jar+B.jar
main-sources.jar=A-sources.jar+B-sources.jar
main-javadoc.jar=A-javadoc.jar+B-javadoc.jar
How can I manage it?
We have been in exactly the same situation for some time now. We want to publish a single artifact for our clients to depend on, although internally the product is developed through a few separate component projects. I got it done eventually (with compromises), and here is what I learned:
Merging jars is not as straightforward as it looks like because there could be things like resource files within a jar that are not
always namespace-ed. It is possible that two of your jars have a
resource file with the same name, in which case you will have to
merge the content of those files.
Javadoc is very hard to merge without accessing the original source
files because it has summary pages (index pages).
So my advice would be:
Think twice, maybe what you really want is NOT a single jar, but a single dependency for your clients? These are different. You can easily have a pom only artifact. Depending on this pom only artifact will simply translates transitively into depending on individual artifacts of your component sub projects. To your client, practically, nothing is changed. Spring Boot takes this approach. To do it, you can create an empty java-library project, make all your component projects its api dependency. You don't even need any source code in this project.
If you really want to merge into a single jar, you can try building a fat jar with customization. The customization is not to pull in 3rd party dependencies.
We use the Gradle Shadow plugin for merging jars. Its original purpose was to build a fat jar, which will include all the transitive dependencies. But it also has a special "shadow" configuration, to which you can add dependencies if you want the dependencies to be exported into POM rather than bundled. So what you need to do:
Define a non-transitive configuration (say bundler) to which you will add your sub-project as dependencies. This is going to be the target configuration for the Gradle Shadow plugin.
Define a transitive configuration (bundlerTransitive) that extends from your non-transitive one. This will be manually resolved in order to find the 3rd party dependencies
in your build.gradle, register an afterEvaluate closure, where you find the level two dependencies of the resolved transitive configuration, add them to the shadow configuration. The reason for level-two is that level one dependencies will be your sub-project artifacts.
After all the above, the artifact produced by shadowJar task is the one to be uploaded to maven. You will need to configure the shadowJar task to remove the classifier (which is shadow by default)
Here is a complete example (build.gradle) of bundling vertx-web and all its dependencies within the io.vertx group:
plugins {
id 'java'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '5.2.0'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
configurations {
bundler {
transitive = false
}
bundlerTansitive {
extendsFrom bundler
transitive = true
}
}
dependencies {
bundler "io.vertx:vertx-web:4.0.0"
bundler "io.vertx:vertx-web-common:4.0.0"
bundler "io.vertx:vertx-core:4.0.0"
bundler "io.vertx:vertx-auth-common:4.0.0"
bundler "io.vertx:vertx-bridge-common:4.0.0"
}
shadowJar {
configurations = [project.configurations.bundler]
classifier ''
}
publishing {
publications {
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
}
}
}
project.afterEvaluate {
// this is needed because your sub-projects might have inter-dependencies
def isBundled = { ResolvedDependency dep ->
return configurations.bundler.dependencies.any {
dep.moduleGroup == it.group && dep.moduleName == it.name
}
}
logger.lifecycle '\nBundled artifacts and their 1st level dependencies:'
// level one dependencies
configurations.bundlerTansitive.resolvedConfiguration.firstLevelModuleDependencies.forEach {
logger.lifecycle "+--- ${it.getName()}"
// level two dependencies
it.children.findAll({ ResolvedDependency dep -> !isBundled(dep) })
.forEach { ResolvedDependency dep ->
logger.lifecycle "| +--- ${dep.name}"
project.dependencies.add('shadow', [group: dep.moduleGroup, name: dep.moduleName, version: dep.moduleVersion])
}
}
logger.lifecycle '\nExported Dependencies:'
configurations.shadow.getResolvedConfiguration().getFirstLevelModuleDependencies().forEach {
project.logger.lifecycle "+--- ${it.getName()}"
}
}
For javadoc if you don't care about the index (compromise, as I said), then it is just a jar task with a copy spec:
configurations {
javadoc {
transitive = false
}
}
dependencies {
javadoc 'com.my:component-a:1.1.0:javadoc'
javadoc 'com.my:component-b:1.1.0:javadoc'
javadoc 'com.my:component-c:1.1.0:javadoc'
javadoc 'com.my:component-d:1.1.0:javadoc'
}
task javadocFatJar(type: Jar) {
archiveClassifier.set('javadoc')
from {
configurations.javadoc.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
}
This cannot be done with maven-publish directly, but one can add individual java-library modules and package each of them with sources and docs. With Gradle this would be a simple jar task, but when the artifacts are publicly available ...such transitive dependencies should better be provided by a meta package; nothing but Maven (Local/Central) dependencies, instead of embedded JARS. In this case, this would be just another module (which obviously would only build after having published the others).
And concerning the concept, that it would require any "merged" JavaDocs ...
https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources
While they're referenced (Maven Central) in *.pom, Gradle will be able to find them.
Just use repository mavenLocal() instead of mavenCentral() for testing purposes.

How to publish and use gradle plugin with dependencies on local project?

I am creating gradle plugin which has dependency on my other local module. Some of its gradle build look like this:
dependencies {
compile gradleApi()
compile project(":myDependencyProject")
}
publishing {
publications {
maven(MavenPublication) {
groupId = 'org.my.gradle.plugin'
artifactId = 'some-name'
version = '1.0-SNAPSHOT'
from components.java
}
}
}
gradlePlugin {
plugins {
jsonPlugin {
id = 'org.my.gradle.plugin'
implementationClass = 'my.implementation.class'
}
}
}
When I publish my plugin using gradle publishToMavenLocal and after that I try to use that plugin in another project it fails with this error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':my-project'.
> Could not resolve all artifacts for configuration ':my-project:classpath'.
> Could not find org.my.gradle.plugin:myDependencyProject:1.0-SNAPSHOT.
Searched in the following locations: ...
In simple words it could not find dependency for myDependencyProject project. That is why as a next step I tried to create a fat jar and publish it but I have got the same error (the code for gradle plugin was same except I have changed from components java to artifact shadowJar).
Can someone help me how can I publish gradle plugin with its local dependencies and use it in another project ?
Thank you very much for any help.
We ended up using the Gradle shadow plugin to include our module in the published artifact.
One thing that was important to us though, was to only include the local library in it to prevent our end consumer from having 2 copies of some library (such as Kotlin). So we filtered the dependencies
shadowJar {
dependencies {
include(dependency(':your-module-name:'))
}
}

Publish Android library with external dependencies

I have an Android closed source module that will be be used as a library in other projects. It contains external dependencies.
To publish it, I'm creating a Maven artifact with the following gradle task:
apply plugin: 'maven'
def coreAarFile = file('...build\\outputs\\aar\\android-sdk-release.aar')
artifacts {
archives coreAarFile
}
uploadArchives {
repositories.mavenDeployer {
repository(url: "file://.\\mvn-repo")
pom.project {
groupId 'a.blabla'
artifactId 'blabla-sdk'
version "1.0.0"
}
}
}
It generates the .aar file, the pom.xml, etc without problems.
Then I create a project that have a dependeny to my library declared. It works until it needs to access to the external dependencies, when throws a class not found exception.
How can I edit my gradle task to include external dependencies or at least a reference to them? They are published in mvnrepository.com and github.com.
I moved uploadArchives to the build.gradle of the module and removed the artifacts element. It works!
Thanks to CommonsWare for pointing to the right direction.

spring-boot gradle plugin messes ivy dependency configuration?

Below is my gradle build script:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
}
}
apply plugin: 'spring-boot'
apply plugin: 'base'
task wrapper(type: Wrapper) {
gradleVersion = '2.12'
}
repositories {
ivy {
url 'my.url'
}
}
dependencies {
archives group: 'my.group', name: 'artifact.name', version: '16.06.29.5144', configuration: 'dist'
}
In it I try to add one dependency to archives configuration. This is dependency published into Ivy repo and it has several configuration, among them a dist configuration. But it does not have default configuration.
Now, if I run gradlew dependencies I get the following error:
Execution failed for task ':dependencies'.
Could not resolve all dependencies for configuration 'detachedConfiguration4'.
> Module version :gtest:unspecified, configuration 'detachedConfiguration4' declares a dependency on configuration 'default' which is not declared in the module descriptor for my.group:artifact.name:16.06.29.5144
When I remove spring-boot plugin, then error disappears and I see expected output:
archives - Configuration for archive artifacts.
\--- my.group:artifact.name:16.06.29.5144
Any ideas why spring-boot plugin breaks dependency on custom configuration?
Your custom artifact looks to be another trigger of a bug/limitation in Gradle. The failure's occurring due to some logic in the dependency management plugin that Spring Boot's plugin uses that, among other things, ensures that any exclusions declared in dependencies' poms are applied as intended.
You can work around the problem, at the cost of perhaps having to declare some additional exclusions, by telling the dependency management plugin not to apply Maven exclusion semantics:
dependencyManagement {
applyMavenExclusions false
}

Categories

Resources