Maven: download file and run command to build dependency - java

Recently, a project I need as a dependency for some of my programs has switched to providing patch files instead of actual jars (legal reasons).
They included a small tool to automatically patch your existing jars with the new update you downloaded.
I could write a small program that automatically downloads and patches the file, all I need is a way to tell maven not to download the file but to run a command and then use the file from my local repo.
Is there a way to do this (maybe using a custom plugin)?

You could write a small ant task run the tool and call this task from your maven build using maven-antrun plugin.
You could also write your own maven plugin but for such a simle task I would not recommend it.

The reason why your IDE does not find the dependency is that it is not published anymore (not the version you seek apparently).
Building the artifact and installing it locally as #Joe suggested is an elegant solution to solve your issue from my perspective.
The advantage is twofold:
Your IDE can seamlessly find the missing artifact
You can keep multiple version of that dependency (one for every new patch) and thus reproduce previous (working) build in case a new patch breaks something.
if you have a local repository, it is even better as this would maven the dependency available to all your team.
Of course you would still need a tool to download new patch, apply them and deploy the produced artifact to the repository automatically. But doing this as a separate task give you more flexibility concerning the tools you could use.

Related

Java dependancy management on GitHub private repos?

My team uses a GitHub.com organization to keep all of our source code in private repos. (Prior, our old workflow was emailing Dropbox links). Most of the time each repo is one separate project with no dependancy of any other (the only dependancies are on third-party open source libraries). Or if there is some dependancy, then the .java files have just been copy pasted into the other project.
I've recently been splitting up some of my code into reusable modules, but I don't know any way to do the dependancy management when I use the libraries I'm creating in another project.
I know with Gradle you can add a git repo like this:
gitRepository('https://github.com/user/project.git') {
producesModule('user:project')
}
but I don't know if there's a way to make it work with private repos, and I don't know if there's a way to specify versions.
My currently solution is to just build the library JAR, and keep track of the binary version with GitHub release tagging, and when I need to use the library in another project, I download the desired version of the JAR (typically the most recent) and add it to a local /lib/ folder in the other project and import the JAR into the module path as a local JAR. Of course I need to go through the whole process again manually if I want to make a change to the library.
I also heard you can set up private Gradle or Maven servers and some companies do that, but I guess that would mean migrating away from GitHub.com?
Is there any way to make this work (either Gradle or Maven, it doesn't matter) to manage dependancies between GitHub private repos?
Can someone tell me, what is the most sensible way (or ways) to solve this?
Thanks.
What you need is a very typical maven/gradle based setup where
each of your projects will be producing an artifact with a coordinate
of the form group:name:version
your projects do not have to be explicitly aware of each other. They depend on the artifacts produced by other projects. This is called binary dependency
for a project to locate a binary dependency, you will need a central registry where you can publish all your artifacts to. GitHub has a product called GitHub Package for precisely this purpose.
If you don't want to use GitHub Package yet, or your setup (number of projects, size of each projects, size your team) is small enough, you can locally checkout all the projects and include them into a gradle composite build so that binary dependencies will be substituted with local project dependencies. The good thing about the composite build is that when you decide to invest in a package registry, your build.gradle requires no change at all.
BTW, where you run your private package registry does not really matter. You can use the GitHub Package, or some other hosted services, or even run e.g. jfrog artifactory on your own server. It is completely unrelated to where you host your source code, so you dont need to migrate away from GitHub in any case.

Opendaylight: Deploy changes to Netconf source code in Integration/Distribution Code

TL;DR -> How to integrate a local Opendaylight Karaf App in the Opendaylight integration/distribution project, for local use? I am not looking to publish my code to upstream to official opendaylight repositories.
I am trying to understand how to make changes to source code of certain features in Opendaylight to fulfill my custom use-cases.
For this, I downloaded the Netconf Source code from "https://git.opendaylight.org/gerrit/netconf" and the distribution source code from "https://git.opendaylight.org/gerrit/integration/distribution".
I made certain modifications in the Netconf Code and built it using mvn clean install -Pq -Dcheckstyle.skip.
Now, how do I go about integrating these updates in the integration/distribution project?
FYI:
I am working on ODL "release/oxygen-sr2". However, I realise that newer versions are available and I am open to shifting to them.
Using Java 8 and Maven 3.6.0
I had been suggested that I could just maven build the Netconf Project code and run Apache Karaf from there. Any other feature could then be installed via the Karaf CLI. But, my use case would require modifications on multiple existing features and even creating a new feature. Therefore, this solution also doesn't work for me as I would still need to integrate everything in one central project.
Actually, it's pretty simple, but maybe not obvious. Build all the projects you
want locally, then build the integration/distribution project. Any artifacts it
finds in the local m2 repo will be used for the final int/dist karaf that will
get created.
in other words, for every project you want to customize, pull that repo, make
your changes, build it. Then as a last step, build the int/dist project.

How to develop a library and a program that uses it using Gradle

I have a library and a program, both under my control and built using Gradle. What's the best way to develop these two at the same time?
I have set up a private maven repository to distribute the library and that's working, but I don't want to release to that repository every little experiment I make during development. It's slow and disruptive to users of the library.
I tried installing the jar to the local maven repository as explained here: Gradle alternate to mvn install but the project that's using the library is not picking up that newly installed version.
I think, you can try to use multi-project builds for that if it's possible. But you will likely need to restructure both your current projects to become modules of the same new project.
What's the best way to develop these two at the same time?
It depends by how the team is organized and what are your policies.
Of course if the team can use a git repo and access to the source code you can just use git without pushing a new version on the maven server for each commit or push.
Otherwise if other users can only use the final library, you have to push the version on the maven server.
I have set up a private repository to distribute the library and that's working, but I don't want to release to that repository every little experiment I make during development. It's slow and disruptive to users of the library.
Every maven repo has 2 different repositories:
release
snapshot
Usually release repo is used only for stable releases and the snapshot repo is used to publish little change, beta release and so on.
In any case it is not required that every changes in the code is pushed in the maven repo (it is a your choice)
It's slow
The time to upload artifacts usually is not so big, in any case you can evaluate to push the release in the maven repo with a CI server.
The best method seems to be to make one project include the other one when present by adding:
if (file("../libraryproject").exists()) {
includeBuild "../libraryproject"
}
to the settings.gradle file of the project that uses the library. That can be committed to the source code repo because when that directory doesn't exist, the dependency will be included in the traditional way.
This is called Composite Build in the Gradle world, IntelliJ seems to handle properly and theres'a recorded webcast showing the whole setup: https://www.youtube.com/watch?v=grPJanXfRPg

IntelliJ plugin: maven, gradle and travis-ci

Currently, my built structure for a plugin in is a bit messy: I'm using the normal IDEA project file to build the plugin locally. When I push it to the repo and travis-ci is building it, it uses the maven pom.xml because for travis to work, it always has to download the complete IDEA sources.
Although this works, this has several drawbacks:
I need to keep two built mechanisms up to date. This is
When a new IDEA version is out (every few weeks), I need to change the SDK in maven and in my IDEA settings
When I add a new library, change resources, etc. I need to do this for two the two settings as well
I ran into problems when I kept the IDEA Maven plugin turned on because it saw the pom.xml and interfered with my local built. Turning it off means, I cannot download libraries with Maven which has the feature of tracking dependencies.
I saw that Gradle has an 'idea' plugin and after googling, I got the impression that Gradle is the preferred choice these days. I have seen Best way to add Gradle support to IntelliJ IDEA and I'm sure I can use the answers there to turn my pom.xml into a valid build.gradle.
However, maybe someone else has already done this or can provide a better approach. What I'm looking for is a unified way to build my plugin locally and on Travis-CI.
Some Details
For compiling an IDEA plugin, you need its SDK which you can access through an installation of IDEA or a download of the complete package. Locally, I'm using my installation for the SDK. With Travis, my maven built has the rule to download the tar.gz and extract it.
It turns out that in particular for building an IntelliJ plugin, Gradle seems to have many advantages. This is mainly due to the great IntelliJ plugin for Gradle which makes compiling plugins so much easier. With Gradle, I could turn my >220 lines of Maven build into a few lines of easily readable Gradle code. The main advantages are that
It takes care of downloading and using the correct IDEA SDK while you only have to specify the IDEA version.
It can publish your plugin to your Jetbrains repository and make it instantly available to all users
It fixes items in your plugin.xml, e.g. you can use one central version number in gradle.build and it will keep plugin.xml up-to-date or it can include change-notes
It seamlessly integrates with Travis-CI
How to use Gradle with an existing IDEA plugin
Do it manually. It's much easier.
Create an empty build.gradle file
Look at an example and read through the README (there are many build.gradle of projects at the end) to see what each intellij property does.
Adapt it to your plugin by
Setting the intellij.version you want to build against
Setting your intellij.pluginName
Define where your sources and resources are
Define your plugin version
Define a Gradle wrapper that enables people (and Travis) to build your plugin without having Gradle
Create the gradle wrapper scripts with gradle wrapper
Test and fix your build process locally with ./gradlew assemble
If everything works well, you can push build.gradle, gradlew, gradlew.bat and the gradle-folder to your repo.
Building with Travis-CI
For Travis you want to use the gradlew script for building. To do so, you need to make it executable in the travis run. An example can be found here.

What is the most elegant solution to managing various Java external libraries?

Perhaps the reason I stalled learning Java until now is because I HATE how Java handles external libraries. I'm stuck keeping them in one place, adding them individually, fixing problems with versioning and every time I move/rename them, and copying and writing the classpath over and over each time I release a Java application.
There has to be an elegant solution to all of this. I keep all of my libraries (regardless of task, platform, or other) in their own little folder inside a "lib" folder in my development folder, kind of like this:
Dev
-lib
+JS-jQuery
+Flex-Degrafa
-Java-Xerces
+Xerces-1.2.3
+More libraries
I can use either Netbeans or Eclipse for Java dev, but none of them provide a very streamlined (and not to mention idiot-proof) way of managing all of these.
A nudge in the right direction or an online article/tutorial on this would be greatly appreciated.
You can either use Ant + Ivy or Maven to manage your library dependencies.
If it is only dependency management you're after and you're happy with the rest of your build process, I would use Ivy, as it can unobtrusively manage your dependencies, leaving your existing build process intact. There is a plugin for Eclipse called IvyIDE that contributes your dependencies via a classpath container.
Maven 2 has a steeper learning curve but provides a much richer set of functionality for building your projects and Eclipse integration through m2eclipse or IAM.
Personally I use Maven as I have a large number of projects to work with and Maven is particularly suited to efficient development across lots of projects.
Have a look at the introductory documentation to see what works for you.
Ivy Tutorial
Maven Getting Started Guide
Netbeans 6.7.1's Maven support is quite good and comes out of the box with the IDE.
The Eclipse addon was frustrating enough that I gave Netbeans another try.
A third choice besides ChssPly76's options is to use Ant with the Maven Ant Tasks. I don't know if I'd call any of these solutions particularly "elegant," but they do spare you the need to manage your own lib/ directory and classpath variables.
If you're working on Linux you can install Java libraries with APT or RPM.
Otherwise, I normally check precompiled JARs into a lib directory in my project's version control repository and make sure the names of the JAR files include full version information. E.g. lib/foo-1.5.6.jar, not lib/foo.jar.
To avoid having to manually set the classpath before running your app, you can set the classpath in the Manifests of the JARs themselves to define the dependencies of each JAR file. The JVM will follow all the dependencies when loading classes.
Maven is often more trouble than it's worth, but the ability to open a maven project directly into IDEs such as IntelliJ is excellent. For example, IntelliJ will download all dependencies and have them available without having to run a build first, or an mvn command and then a project refresh. It also isn't necessary to re-generate the project every time a dependency is added. I work with a number of Eclipse developers who switched to IntelliJ for this alone.
However, one shortfall of Maven is that many libraries (or versions of libraries) are not available on public repositories. Therefore it is often necessary to set up a local repository such as archiva. In ant, it would just be a matter of adding it to the lib directory in the repository.
Maven can also attack when you need to do something that maven doesn't directly support via a plugin. What would normally be a few lines of ant can often turn into a morning's worth of work.
Finally, buildr is an excellent way of using Maven's dependency management and plugins, while also supporting ad-hoc tasks.

Categories

Resources