Optional testFixtures in Gradle - java

I would like to add the java-test-fixtures plugin to a custom conventions plugin under buildSrc that I simply add to any of my modules. By doing so I only need to add my custom conventions plugin instead of having multiple (and different) plugins for each sub-module. By doing so the build won't work anymore if a sub-module does not have a test fixtures source set (/src/testFixtures/java/...). Is there any way in Gradle to make the usage of java-test-fixtures optional?

Related

Can Gradle precompiled scripts plugins use java-gradle-plugin?

(Gradle version 7.3.3)
I'm following the documentation
regarding the gradle precompiled scripts plugins.
Plugin to use
The groovy-gradle-plugin is used in this case.
I tried with the java-gradle-pluginbut it doesn't seem to generate the plugin classes.
Is this to be expected?
Plugins id's
Following the documentation:
src/main/groovy/my.java-library-convention.gradle would result in a
plugin ID of my.java-library-convention.
I want to prefix my scripts with: com.mycompany.myproject.conventions-java-library
In this case, the generated plugin classes are named with this full name in the default package.
Is this to be expected?
I expected to find a class named JavaLibraryPlugingenerated in the com.mycompany.myproject.conventionspackage
The groovy-gradle-plugin is used in this case. I tried with the java-gradle-plugin but it doesn't seem to generate the plugin classes. Is this to be expected?
Not fully sure what you are asking.
If you meant applying the java-gradle-plugin instead of the groovy-gradle-plugin, this of course will not produce any plugin classes. How should the Java plugin know about Groovy source files?
Why I'm not sure whether that is what you asked is, because the groovy-gradle-plugin already automatically applies the java-gradle-plugin. So if you want to use Groovy DSL precompiled script plugins, just apply the groovy-gradle-plugin as documented.
Plugins id's
For Groovy DSL precompiled script plugins you can only follow that convention if I remember correctly. With Kotlin DSL precompiled script plugins you can either follow that naming convention or you can also use package statements inside the script to "properly model" the plugin id.

Gradle Composite Build with different project types (ant, maven)

Is it possible to create a Gradle Composite Build using maven or ant+ivy projects as subprojects?
If yes, how to do it?
I checked the documentation at here and it has some reference to ant and maven, but not so clear about this type of integration.
My goal is to have a composite build where the app is a gradle project and the libraries can be gradle, maven or ant and can be easily managed in a IDE like eclipse or IntelliJ
I don't think you can use Gradle to do the inter-projectType build orchestration. But you can transform the other projectType (maven or ant) into using Gradle, and then you can start to use composite gradle build between these modules. With that said, you probably have to maintain two build tools for the maven/ant module, if you still need them.
NOTE The composite build concept is essentially to help the cross-project development (intends to replace the binary dependency), it actually makes sense that you need to use Gradle across the board.
The documentation reference you mentioned are actually for the artifact publication flow (maven-publish, ivy-publish), that won't be useful in the build integration.

Is Maven similar to npm?

As I have worked with npm which looks for dependencies in package.json file and download it for you. Similarly, I see a pom.xml file in Java project. Does maven looks in this file and download dependencies for me. Can I pass around this pom.xml file like package.json, rather than giving the dependency jars ? Are these tools similar and just build for different platforms ?
Same tool, different language?
Maven is the most popular build and dependency resolution tool for Java, just like NPM is for JS. But it's not just the same tool for a different language. There are obviously huge differences between Java and JS builds, and these differences are directly visible in the way Maven operates. For example, while many JS tools rely on Git to do some heavy-lifting, Maven works with custom filesystem-based Maven repositories, as Maven predates Git and needs to handle binary artifacts, which Git historically didn't handle well. In Maven there's a clear separation between sources and binaries, while they are often the same thing in JS world.
Maven basics
Maven in its purest form follows a declarative model, where pom.xml (similar to package.json) defines different properties of the build, but contains no scripts. The disadvantage is it can be a challenge to fine-tune some aspects of the build without using scripts as you have to rely on plugins. The advantage is it can be easier to understand other builds just by looking at pom.xml, as they usually follow the same approach without too much customization. Gradle is a popular Groovy-based tool built on top of Maven standards and conventions, and is specifically designed to simplify pom.xml and break this "no script" barrier.
Referencing your dependencies
Similarly to package.json, you don't work with pom.xml of your dependency directly, but rather define dependency coordinates and let your build tool handle the rest. In Maven the basic form of these coordinates is GAV (groupId, artifactId, version).
Flat dependency tree?
Based on comments in the other answer, Maven provides "flat dependency tree", not "nested dependency tree" that NPM provides by default. Maven does not allow multiple versions of the same dependency. If it happens that different versions are requested, Maven uses dependency resolution to pick a single version. This means that sometimes your transitive dependencies will get a different version than they require, but there are ways to manage this. However, this limitation comes from Java, not Maven, as (normally) in Java a class loader will only provide access to a single class definition even if multiple definitions are found on the classpath. Since Java is not particularly good at handling this, Maven tries to avoid this scenario in the first place.
Note: since npm v3 the dependencies are flatten. The alternative package manager yarn also does the same.
Maturity
Furthermore, Maven is considerably older than NPM, has a larger user base, huge number of custom plugins, and so far could probably be considered more mature overall. Sometimes Maven is used for non-Java or even polyglot projects, as there are plugins for handling other languages or specific environments, such as Android. There are plugins that bridge Maven and other build tools, such as frontend-maven-plugin that actually handles multiple JS build tools.
Yes they are similar in the context that their main purpose is to provide a way describing the project dependencies, instead of keeping them within the project code, and their secondary purpose is to provide developers with an easy way to perform, define and share dev-time/build-time tasks. Both of the above are expressed inside a descriptor file.
Now deciding which one to use is, most of the times, straightforward because it depends on the primary language you are working on. A rough grouping is:
java: maven
javascript/typescript: npm
Below I provide a detailed explanation of the common features and differences. I use | to separate between maven | npm terms respectively:
Common features:
Both tools support dynamic fetch of dependencies ( artifacts | packages ) based on a descriptor file pom.xml|package.json, and also allow you to deploy | publish your own artifacts | packages.
They both have a default public repository | registry ( http://repo.maven.apache.org/maven2/ | https://registry.npmjs.org), but 3rd-party can also be used (via settings.xml|.npmrc ).
They both support the concept of build-level dependencies (plugins | devDependencies used in scripts). *Maven supports provided dependencies also but this does not seem to apply to npm, since javascript is rarely deployed into containers.
They both support dependency namespacing: groupId|scope
Differrences:
maven has an additional local repository(cache):
No need to fetch again the same dependency for differrent projects.
Artifacts that are installed locally, are automatically accessible by other local projects.
dependencies from a project build in maven are downloaded in <homedir>/.m2. With npm they are downloaded in <projectdir>/node_modules.
Building in maven is commonly a one-step process: mvn package (fetch deps , build). In npm it is a 2-step process: npm install (fetch deps) , npm build (build)
maven defines build lifecycles (for building,testing,deploying) consisted of phases, to which default operations(plugin goals) attach, based on differrent packaging options(.jar,.war,.ear e.t.c). You can then overwrite these operations, or inject new ones (via the plugin system). This provides kind of an out-of-the box solution for build,docgen,test,deploy e.t.c.
npm approach is more simplistic ( see: scripts)
Due to the above, npm is labeled as a package-management tool for javascript while maven is labeled as a build-automation and dependency-management tool for java.
In maven setting-up the build process more commonly involves editing the pom.xml.
In npm it involves writing code or configuring complementary build tools like gulp,webpack e.t.c
For some reason version ranges defined by users in npm modules, are much more loose than in maven. This can cause issues with transitive dependencies, that is why an additional file was recently added: package-lock.json
With npm it is much more straightforward to start a new project: npm init. With maven, you need to know how to write a minimal pom.xml, or read about archetypes.
In general it is much more common to edit pom.xml than package.json. E.g. adding dependencies in maven is done manually (or via IDE) while in npm via command line.
As with all build tools, you can call one tool from inside the other, but I think its much more common to call npm from inside maven, than the opposite.
npm supports dev,production builds. In maven this needs to be defined through profiles.
yes. it's a similar packaging tool for java. look for gradle also which gives you more liberty with groovy language, but for start you can use maven to organize your dependencies. you include them as tags there and maven does the job for you.
it traverses the dependency tree and downloads all the appropriate jars.
Yes, same with gradle, but they are not user friendly as npm.

How create properties (variables) in sbt which are reusable across builds?

With maven I can create a parent pom.xml and extends it everywhere. Also in parent pom I can define some general properties like library version and other properties which are wanted to share across several imdepeneded projects. How to do this with sbt if projects are different and they do not build from one root project/folder?
Important
The question is not about multi project build!
Not tested, but should work:
Create a normal SBT project, define your desired settings, etc. there. Let's say it's in the path ~/parent.
Note that the project folder of an SBT project is itself a project.
You can depend on external projects from file system or VCS in SBT. In the builds where you want to reuse parent project, create project/project/Build.scala (or project/build.sbt) if it doesn't exist yet, define the project as usual and and add a dependency on ProjectRef(file("~/parent"), "project").

Maven: Does project inheritance or aggregation better support this scenario?

I am porting a project from ant to maven. The project consists of a core set of classes which gets jar'd and used by 3-4 other subprojects. Importantly (I think?), the core jar has its own configuration that gets set at build time, and each subproject also has configuration set at build time. In the old ant system, anytime I built one of the subprojects with something like...
ant -Dconfiguration=stage clean dist
...it would build the core jar using the same (stage) configuration, and copy it into the classes dir of the subproject's build. I'd like to duplicate this functionality using maven. From the reading I've done, it seems like Maven can handle this using either project inheritance or aggregation. What are the chief differences between the two methods, and which would you recommend for the use case I've described?
Inheritance is used for sharing common things between your projects, such as 3rd party library dependency or properties, or scm locations. Aggregation is used to build your projects as a group. You want aggregation, but that doesn't mean that you won't also be using inheritance to factor out common stuff.
Update: also keep in mind that maven is not just about building (unlike ant), it is about dependency management, so you could just create dependencies on your core and not use aggregation at all. You would depend on a particular version of your core. This however doesn't satisfy your requirement of building everything at once.

Categories

Resources