Gradle dependency without version - gradle

I am migrating a larger project to Gradle and I have a problem migrating one of the dependencies.
Previously we had all of our dependencies locally in a lib folder right inside the project.
We now shifted to retrieving them the Gradle way via MavenCentral and other repositories. Some of the libraries that we use cannot be retrieved from any public repository. Therefore we set up an internal repository (Sontype Nexus) and uploaded the libraries manually.
Now, there is one library for which this does not work. I'll refer to that library as SAMPLE. The issue is, that the library checks the classpath at runtime and looks for itself. Problem is, that the library only looks for a "SAMPLE.jar". But because of the Repository-restrictions the jar is now called "SAMPLE-{version}.jar". Therefore the library fails at runtime with an exception.
I have already managed to "deploy" the jar to Nexus without a version number via HTTP PUT. But now I can't declare a dependency inside Gradle as I am obligated to specify a version.
Is there any workaround to this situation that does not include changing the library?

Related

Does "build with local dependencies" exist in Maven without multi-module?

I have a set of applications, all use Maven and the local repository. The applications form a dependency tree using <dependency> in their pom.xml. All of these projects have -SNAPSHOT in their version.
Is it possible for Maven (or some compatible dependency manager) to build an application together with all of its local dependencies whose source changed?
I do not want to create a multi-module project, because:
the projects are exactly libraries, not modules;
I do not want an additional complexity just to have a form of build which is already precisely defined;
I want the process to be dynamic: if a library is mature enough to be put into a remote repository, it would be no more rebuilt with the main project and that's ok.
For now, there is a lot of refactoring, moving code from one library to another etc. and it happens often that substantial parts of the dependency tree need to be rebuilt. I thus need to manually write mvn install in several projects in order to assure that there is no stale code.
No, it doesn't work. Even with a multi-module project, maven does not detect which modules have changed sources in it and which do not.
There was a (flaky) implementation in Maven 2, but it was not continued in 3.x, see How to get maven 3.0 to only build modules with local scm changes
I hoped they would include it again in maven 4, but I didn't see it yet: https://maarten.mulders.it/2020/11/whats-new-in-maven-4/
I once did a similar setup, but had to use shell scripts with some git magic to get it working.
You can also decide to put your libraries in separate repo's from the start, and use the repo tool that google uses for android development: https://github.com/GerritCodeReview/git-repo/blob/main/README.md
Once you run mvn install on the particular Maven project, it will be accessible for all other Maven projects, which are on the same workstation, during dependency collection (before the compile phase).
Official Maven Build Lifecycle description:
install - install the package into the local repository, for use as a dependency in other projects locally
It's not necessary to keep libraries as part of the same project(or have it as a multi-module project). But once you want to share those libraries with your teammates, you would need either to force them installing libraries locally (as you did), or store those libraries at some external repo, like Artifactory or Nexus

How to correctly import a Maven dependency that I altered and re-built into an existing project?

I have a Maven dependency, pulsar-log4j2-appender, which I forked and changed the source code because it was throwing exceptions in my project.
After changing the source code, I ran the maven package command to build the jar and imported it into my project (in Intellij: Project Structure | Modules | Dependencies | Add JARs or directories...).
However, when I run the application, it seems like it's not able to find that dependency because the Pulsar appender which I declared in my log4j2.xml file isn't being configured.
Am I importing the JAR properly? I'm wondering if the JAR needs to be within the org.apache.pulsar namespace to be imported properly.
For example,
This is what the dependency looks like unaltered:
And this is what it looks like when I modify and build it myself:
If you modify the code from an open source project you should change both the groupId and the artifact id. If you do not you will have problems and future developers will say your name in ways you do not want to hear.
Changing these are necessary so that Maven knows to use your version instead of the publicly available version. Also, when people look at your project and see the groupId and artifactId from the "real" project they will naturally assume that is what is being used (which is why they will curse you if that is not the case). In addition, you will have to do something convoluted to get Maven to use your dependency reliably.
The practice I have followed is the prepend "com.mycorp", where mycorp is my employer's name, to the groupId and add mycorp into the artifactId. The only downside to this is that you must ensure that the "real" artifact's coordinates are not referenced as a dependency or as a transitive dependency or else you will have duplicate classes on the class path.
Finally, your best bet is to create a pull request for Apache Pulsar with your fix so that other people experiencing the same problem you are get the benefit of it.

After making a Gradle groovy jar library how to make it re-usable for multiple local projects?

Here I read about how to make a Groovy library .jar ... i.e. pretty much the same as making a Groovy (standalone) project. But I'm not clear what you do then with the resultant .jar...
Say I have two Eclipse "proper"/"standalone" projects (I'm using Groovy for everything) and I want them to share a third Gradle library project of mine as a dependency, which is merely a library of classes... how are my standalone projects expected to find the latest .jar version of the library which they're both using...?
My expectation would be that somehow these versions of the library .jar would have to under GRADLE_USER_HOME (i.e. same location as all other dependency .jars).
Then I would assume that in the build.gradle of both standalone projects you'd have a line like
compile 'mylibrary:mylibrarymodule:3.+'
... of course the first part of these compile directives normally involves a "domain name in reverse" ... and this is normally used by a repository like Maven. How does it work with something which doesn't need to be published?
NB at the time of writing I don't have a Maven account as such and have no idea whether "publication" for re-use of a local common library project like this is essential or not.
Naturally, when I distribute versions of my standalone projects they will need to be packaged up with the library .jar in question.
A link to a how-to for a case like this would be more than welcome: I haven't found it under gradle.org.
If you are developing by yourself, you can use maven-publish plugin to publish your artifacts to local maven repository(you don't have to install maven for this) and on your dependent project you can simply say use mavenLocal repository for dependencies.
If you are on a company, I suggest installing a repository manager and deploy your artifacts to this repository so others can use. You can use their respective plugins to deploy easily. (Gradle Artifactory Plugin, Gradle Nexus Plugin, these are just deployment plugins, you have to setup respository manager to. There are other repository management tools also.) Doing the above process from CI server is the preferred way.
To use latest version of a dependency, you can use Gradle Versions Plugin. If the versioning happen often, using snapshot versions also a possibility.

Statically linking maven and gradle dependencies

I am using the hector & astyanax projects. These projects used to require maven, and now astyanax requires gradle.
I would like to statically link one of these projects to my java project (which is not built using maven/gradle). I am not interested in updating the version of astyanax every time they make a new release. I am not interested in mavenizing/gradelizing my own project.
So, two problems arise: 1. Getting the astyanax jars. 2. Getting the depenedency Jars.
At first, not having time to thoroughly understand maven (get off my lawn!), I copied all of the jar files in my global .maven directory into my project, and linked to them. Problem is, it's a pretty messy solution.
Is there an easier way to get all jars needed to use a gradle/maven library? (While I don't mind using gradle to build astyanax, I don't want to use it to build my own project).
Getting jars for distribution, seems like a very basic use case, am I missing a simple way here?
astyanax is published to maven central as com.netflix.astyanax:astyanax:1.56.42. Any build tool (Grails, Maven, Gradle, Buildr, SBT) that resolves from Maven can make a dependency on Astyanax and have its dependencies transitively downloaded. That fact that it's built with Gradle doesn't change how it's consumed.
From your question, it's unclear how you want to resolve these libraries. If you don't want to use a tool (Grails, Maven, Gradle, Buildr, SBT), then you'll have to manually navigate every dependencies and its dependencies from Maven Central. It's quite uncommon for a modern java project to manually download dependencies anymore, the practicalness given the complex dependencies graph make it prohibitive.

How to ensure Maven dependencies have expected source version?

I am trying to build multiple Maven libraries out of the same source control. I do not have a strong business need for versioning as the only requirement I have is simply that when a library or application is built, all the in-house Maven libraries it relies on are using the same source version.
I am using buildnumber-maven-plugin to obtain the source version as ${buildNumber} in Maven. However it is illegal to append this to the Maven version coordinate (which would have solved my problem). I am wondering if there is another way to expose this in a Maven project then check it in a client (i.e. dependee) project.

Resources