I am currently migrating several Maven projects to Gradle. Some of them are simple, some are multi-module builds, but all are stored in separate Git repositories. All projects rely on a common "Master POM" which defines the following sections:
organization
properties
reporting
distributionManagement
build / plugins
repositories
For example, all projects use the same Maven repository (Nexus).
How can I introduce this kind of common configuration to Gradle, ideally stored in a separate Git repository?
you can check out this sample.
Generally sharing build logic in Gradle is achieved through plugins mechanism.
This documentation describes how to create plugins, which can then be published to maven repository and applied in different projects.
For sharing dependency versions there is version catalogs or platforms
Related
I want to publish a common build script which i will include across various projects in my application.
This will contain only the common set of dependencies, i.e dependencies with particular versions that will be common across all the artifacts in my enterprise application..
My applications will refer to this file from the url.
How can i achieve this?
EDIT1: my exploration in this direction is based on this answer on SO:
How to share a common build.gradle via a repository?
There are a few different options for this.
One is to publish a project with the dependencies you want to share defined as API dependencies. Projects that depend on this will inherit the dependencies.
Or you could write and publish a Gradle plugin that will configure your projects with the common dependencies. Projects can apply the plugin, and will automatically be configured in a certain way. (You don't need to publish a plugin to do this - first try creating a project-local buildSrc convention plugin.)
I would actually recommend neither of these approaches.
It's easy to get into a tangled web of dependency hell when transitive dependencies are inherited. It's likely that at some point some dependency will clash, and excluding dependencies can be a big headache, and will easily cancel out any benefit in trying to reduce a little duplication.
Additionally, it's nice when a project is explicit about its dependencies. Being able to look at a build.gradle.kts and understand exactly what dependencies are set is very convenient.
Instead, what I would recommend is controlling the versions of common dependencies in a central location. This can be achieved with the Java Platform plugin. This plugin can be applied to a single build.gradle.kts file, and it lists all versions of all possible dependencies. (It can also import existing Maven BOMs, like the Spring Boot BOM).
Now, all subprojects can add a platform dependency on the 'Java Platform' project.
dependencies {
// import the platform from a Maven repo
implementation(platform("my.company:my-shared-platform:1.2.3"))
// or import a platform from a local project
implementation(platform(":my-project:version-platform"))
// no need to define a version, if it's defined in the platform
implementation("com.fasterxml.jackson.core:jackson-databind")
}
This is the best of both worlds. Projects can be explicit about their dependencies, retain autonomy, while the versions can be aligned across independent projects.
Ive been working off the guides which mention to start by doing
gradle init
on the project. So this creates build.grade. However, the rest of the gradle file is very thinly padded. Im quite new to doing these conversions, but broadly speaking, what would be the next step to get things in harmony?
The Gradle docs lists the following features of the Maven POM conversion:
Uses effective POM and effective settings (support for POM inheritance, dependency management, properties)
Supports both single module and multimodule projects
Supports custom module names (that differ from directory names)
Generates general metadata - id, description and version
Applies maven, java and war plugins (as needed)
Supports packaging war projects as jars if needed
Generates dependencies (both external and inter-module)
Generates download repositories (inc. local Maven repository)
Adjusts Java compiler settings
Supports packaging of sources and tests
Supports TestNG runner
Generates global exclusions from Maven enforcer plugin settings
This means, every required functionality beyond these features must be added manually, either by searching and applying plugins equivalent to the ones used in Maven or by implementing the functionality on your own.
When you define multi module project in Maven, you have one root project and its modules. When you build the root project, Maven transitivelly builds all its modules in correct order. So far pretty similar to Gradle.
But with Maven, you can clone only one submodule from repository and build it locally without need to download the whole project structure. This is because you define dependencies on other modules within the same project just as any other external dependency and it is downloaded and cached from your local repository (Nexus).
With Gradle, you define cross module dependencies as compile project(':other'). So you need to clone whole project structure from repository in order to resolve and build correctly. Is there any way to use Gradle multi module project support, without having to locally clone whole project structure?
I would argue that Maven's multi-module support is a slapped on after-thought. Unlike Gradle, a project dependency is not a first class concept. Instead the maven "reactor" substitutes local artifacts for dependencies when the GAV (group/artifact/version) matches.
If you'd like to use the same approach in Gradle then you can specify your dependencies using the GAV notation and then use the new composite build feature to join two or more separate gradle builds together and substitute repository dependencies for local source dependencies. Note that that you can define the projects included in the composite using groovy so you could easily script this based on custom logic (eg if a subfolder exists in some root folder etc)
Note that composite build support is a new feature added in Gradle 3.1. Prior to Gradle 3.1 you can use Prezi Pride to achieve the same
Are there any good tools that can scan many levels into maven projects / subprojects and generate reports or charts about all of the dependencies, version discrepancies between the same packages in different projects, etc etc?
Is there some other smart way to manage large maven projects that have several layers of subprojects with a large number of dependencies in each one?
Get a repository manager like Nexus, use the Maven Dependency plugin, use Sonar, use Hudson/Jenkins, check out Sonatype Insight and the Insight for CI plugin, use the dependency viewer in Eclipse, use a parent pom for your organization to centralize dependency versions and so on. Lots to do for you.
You can use Jenkins. It has got all you need to do with a maven project.
Jenkins with sonar the best combination for managing huge maven projects.
Depending on how "deep" you want to go, the maven site builds can use the reporting plugins to generate much of what you want. If you want much more info, then something like Sonar is probably more of what you want.
The simplest solution is to use the maven-dependency-plugin which can produce reports either ASCII or in different formats. Or you use the dependency-hierarchy in your IDE (m2e Plugin Eclipse) to look into the dependencies.
I want to create a maven project, which has to depend on a non maven project which in turn depends on 2 other non maven projects. I do not have ownership of any of the other projects and it would not be possible for me to change anything in those projects let alone the structure to conform to the maven structure.
I asked if I could just get jars -- but was told that because of multiple levels of dependency, it would be "difficult" -- although I haven't understood why.
Is this possible or should I just abandon the use of maven to create my project and go with a regular project with jars in the lib folder?
Inxsible
If you can go with a regular project build that means you must have access to the other project's jar files?
It doesn't really matter how the other project builds them, you can still gain more control over your own build process by loading the jars you depend on into a Maven repository.
I'd suggest using one of the following repository managers:
Nexus
Artifactory
Archiva
They'll give you management screens to uploading 3rd party jars, they'll also a more efficient way to use other Maven repositories like Maven Central.
Once you've got your Maven build process working, you could encourage the other projects to automatically publish their versions into your Maven repo.
They could use the ANT tasks provided by the Maven or Apache ivy projects. Worst case you just continue to load their libraries until they see the light :-)