Upload maven pom.xml to Git repository? - java

I want to publish my Java project on GitHub. I'm not sure if I should upload my pom.xml from Maven in my repository.
I'm using Eclipse without eGit.
On the one hand:
the pom.xml is necessary to know which libraries I used.
On the other hand:
it's a configuration file which maybe shouldn't made public.
it destroys the look of a clean repo, because it's outside of the normal source files.
What should I do best?

it's a configuration file which maybe shouldn't made public.
This is wrong. The POM is indeed a configuration file but it is intended for this file to be public. Actually, quoting Maven guide to uploading artifacts to the Central Repository:
Some folks have asked why do we require all this information in the POM for deployed artifacts so here's a small explanation. The POM being deployed with the artifact is part of the process to make transitive dependencies a reality in Maven. The logic for getting transitive dependencies working is really not that hard, the problem is getting the data. The other applications that are made possible by having all the POMs available for artifacts are vast, so by placing them into the repository as part of the process we open up the doors to new ideas that involve unified access to project POMs.
As you see, this file is actually required so that the artifact can be uploaded to Maven Central.
What should not be public is your settings, i.e. the settings.xml file. It is in this file that you should store any sensitive information, like passwords. Again, quoting the Settings Reference (emphasis mine):
The settings element in the settings.xml file contains elements used to define values which configure Maven execution in various ways, like the pom.xml, but should not be bundled to any specific project, or distributed to an audience. These include values such as the local repository location, alternate remote repository servers, and authentication information.
If you currently store any sensitive information in your POM, you should consider refactoring it to extract this info and put it inside your settings instead.
it destroys the look of a clean repo, because it's outside of the normal source files.
It is a source file in the sense that Maven only requirement is exactly the presence of this file. It describes how to build your application and declares all of its dependencies. To say it differently: this file is a Maven source file, and as such, should be commited along with the project main source files. Without it, no-one can build your application and no-one can also package it.

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.

How include 3rd party jars in maven project (compile, build, package) where adding local maven repo is not an option?

We have a git project that has some 3rd party jars which are not available in any Maven repo and are in a "lib" folder in the project. I need to include them for compiling, building and then package them into the WAR in WEB-INF/lib.
I cannot add them as a local maven repo from the command line because this projects needs to be buildable for anyone cloning the repo without requiring them to run extra commands (I have no way around this requirement).
I saw some people suggesting System scope but that then Maven won't package them into your WAR:
<dependency>
<groupId>com.roufid.tutorials</groupId>
<artifactId>example-app</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/yourJar.jar</systemPath>
</dependency>
How do I get these jars to be used for compiling/inspection, building and then packaged into the WAR?
You can use :
System scope but make the packaging yourself via assembly plugin
A maven repo along with your project (i.e. maven repo on-the-fly, basically same as local repo but without having a extra moving part to worry about because this repo follows your project).
For Maven repo on-the-fly option, you can do as described here (which is, take any already existing Maven repo, which already contains your needed jars, such as your local one, put it in your project, and then reference this repo from your project using relative paths).
I'll assume you've verified that whatever mechanism you might use to distribute these jars would be in compliance with the relevant licenses. If it would, then it seems there would be little reason for the jars' creators not to provide for official Maven distribution, so your best option might be to lobby for them to do that. But if not, and yet for some reason they'll allow for you distributing the jar (either through cloning of your repo, or via a separate Maven repo you maintain):
There are several ways. I give preference to approaches that don't put the jars in the git repo.
Publish a Maven Repo
So it's possible to host a public-facing repo and serve the artifacts that way. The pom can add your public-facing repo to the build, so that those who clone can build without having to run any special commands.
Running your own repo isn't terribly difficult. The OSS versions of Nexus or Artifactory jFrog would probably be perfectly capable.
But, if we're assuming the authors' refusal to publish their own jars via Maven means they don't want them distributed that way, then there's no reason to spend much time on the details of this option. So moving on...
Distribution in the Git Repo
I guess this is what you're doing, though again if Maven distribution violates the license I'd make sure you're splitting hairs the right way in thinking that this doesn't.
So the question would be how to get Maven to deal with the artifacts distributed in this way, and again there are some options.
Your objection to putting the jars in the local repo is that it would require extra commands of the user; but actually this could be automated in the "validate" phase of the build. Binding install:install-file to the validate phase should work.
Alternately, your objection to using system scope is that the file isn't copied into the final war. You might be able to use the dependency plugin to force the issue, but I'm not sure of that. What I am sure of is you could treat the directory containing the jars as a web resource with suitable configuration in the war plugin. (You'd want it to be treated as unfiltered and to map to the WEB-INF/lib folder.)
In any case, if you distribute jars (or other large binaries) in the git repo, I strongly recommend you look at git lfs. This will require one-time configuration by each of your users, but it will prevent your repo from gradually becoming bloated and unusable.
Use forward slash (/) to backslash () in the systemPath.
<dependency>
<groupId>com.roufid.tutorials</groupId>`enter code here`
<artifactId>example-app</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}\lib\yourJar.jar</systemPath>

Best way to add local dependency to Maven project

There are a lot of questions about this, but the answers seem to contradict each other. So I wanted to ask it for my version of Maven (3.0.4).
I have a JAR file that's not part of any maven repository. It's a local dependency. I understand there are two ways to add it to my Maven project.
Add it as a dependency and specify the file path in the <systemPath> property. (No other work needed.)
Create a local repository <my-project>/repo and install the JAR in this repository. Then, add the new repository in my pom.xml file and add the new dependency.
I'm curious which way is better practice? I've heard some negative things about the <systemPath> property, although that way looks faster.
The answer is, it depends...
If you add it as a system dependency it is likely to become path dependent which makes it more difficult to share among other developers. Sure you can also distribute the 3rd party jar relative to your POM via your SCM but the intention of systemPath is more for dependencies that are provided by the JDK or the VM. From the docs about systemPath:
They are usually used to tell Maven about dependencies which are provided by the JDK or the VM. Thus, system dependencies are especially useful for resolving dependencies on artifacts which are now provided by the JDK, but where available as separate downloads earlier.
To install the jar in the local repo is also not friendly for sharing. It requires all developers to "upload" the jar to their local repo before building. You can of course add a script that handles this for you but it is always easy to forget to upload and IMO a better solution is point 3 below. The local install process is described here.
If you are working in an organization where the developers share the POM you should upload the 3rd party jar to a local repository manager. That way you can easily work with the 3rd party jar as if using any other maven enabled jar. Check this link for a comprehensive list on repository managers.
To summarize, if you are sharing the POM with others I would suggest that you upload it to a local repository manager. Otherwise the second option can work for you. As a last option, I would fall back to option number 1.
Also note that this has nothing to do with which version of Maven you are running.
You can add jar to your local maven repository. Usually it located at:
$home_directory/.m2/repository
For example you have expample.jar and you want to add it to your pom as:
<dependency>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0</version>
</dependency>
Then you must add example.jar to:
$home_directory/.m2/repository/com/example/1.0/example.jar
In my case NetBeans do it for me.
The best way I see so far is to use install:install-file goal with maven. You can use the mvn command line to execute it directly with appropriate parameters, or if you are using eclipse EE, you can do so by leveraging the embedded maven and creating a Run Configuration as follows:
Then, you include the jar as follows:
<dependency>
<groupId>mylocal.weka</groupId>
<artifactId>weka</artifactId>
<version>1.0</version>
</dependency>
Of course adjust the parameters as per your needs.
Best,
Haytham

Jar Dependencies in GitHub

I'm setting up a new Java project on GitHub, and I'll have some Apache Commons libraries as dependencies.
What are the best practices to establish that my project needs those jar files? Should I upload the dependencies to my GitHub repository (ugly)? Or use a Maven-like tool for that?
Or is there a way to link a file in another git repository? Apache provides git repositories for they libraries. They are read-only, but I'm o.k. with that, since I just want to use the jars. The bad thing is that they contain all the sources, and I just care about the compiled jar. It seems we can't git submodule just a file.
The two approaches are:
declarative and component-based, where you declare (describe) what components (jars, exe, other binaries) you need for your project to (compile, execute, deploy, etc.), and you use a third-party tool (like Maven/Nexus) to bring those components on demand.
So they aren't versioned in your repo. They are declared/described (like in a pom.xml, if you were to use Nexus)
See also "Difference between Git and Nexus?".
inclusive and system-based, where you complete your project with other project sources/binaries, in order to get in your repo everything you need right after the clone step (no need to call a third-party tool or to do anything: every other part of your system in there).
With Git, especially if those "other parts" are in a git repo (like the apache libs one), then you would declare those sub-repos as submodules of your main repo.
That way, all you keep in your main repo is a special entry (gitlink, mode 160000) referencing a specific SHA1 of another repo (but you can make that submodule follow a branch too, a bit like svn external).
And with sparse checkouts in submodules (as in this example), you even can update those modules for them to checkout only the part of the repo you want (like just the jars, not the sources).
Note that you aren't supposed to store any delivery that you would produce (like jars of your own) in your GitHub repo.
You can associate those deliveries to GitHub releases though.

Importing protocol buffer definitions between Maven projects

I currently manage a few separate Maven projects in which I use Protobufs as a serialization format and over the wire. I am using David Trott's maven-protoc plugin to generate the code at compile time.
All is good and well until I want those project to communicate between one another — or rather, use each other's protobufs. The protobuf language has an "import" directive which does what I want but I'm faced with the challenge of having project A exporting a ".proto" file (or possibly some intermediate format?) for project B to depend upon.
Maven provides a way for a project to bundle resources but AFAIK, these are meant to be used at runtime by the code and not by a goal during the compile / source generation phase — at least I haven't been able to find documentation that describes what I want to achieve.
I've found another way to achieve, and it doesn't involve any Maven magic. Diving into the code for the maven-protoc plugin, I found that this is a supported use case -- the plugin will look for and collect and .proto files in dependent jars and unpack them into a temporary directory. That directory is then set as an import path to the protoc invocation.
All that needs to happen is for the .proto file to be included in the dependency's package, which I did by making it a resource:
projects/a/src/main/resources/a.proto
Now in projects/b/pom.xml, add 'a' as a regular Maven dependency and just import a.proto from b.proto as if it existed locally:
b.proto:
import "a.proto";
This isn't ideal, since files names may clash between various projects, but this should occur rarely enough.
You can package your .proto files in a separate .jar/.zip in the project where they are generated, and publish them in your repository using a dedicated classifier. Using the assembly plugin might help here to publish something close to "source jars" that are built during releases.
Then, on projects using them, add previously created artifact as dependency.
Use the dependency plugin with the "unpack-dependencies" goal, and bind it to a phase before "compile".

Categories

Resources