I don't understand why this is still a matter of discussion after so many years of blood and tears. Maven is dead, everyone else is moving to Gradle (Spring, Android, Hibernate, etc.).
I have been using Gradle now for almost 3 years and I can't be happier. The support is great, they roll out new features at a regular pace, it's fast and incremental build WORKS.
If you work in Java and you are still stuck with Maven, please, take a look at Gradle.
> If you work in Java and you are still stuck with Maven, please, take a look at Gradle.
or ivy? i really haven't spent a lot of time toying with the various build systems. i tend to use ant until manual dependency management becomes ... unmanageable, then maven because i've apparently been brainwashed (i.e. i heard that they use maven at a lot of not-so-bad companies like thoughtworks).
after the article, i do like the suggestion of ivy+buck, neither of which i'd paid attention to before below the clamor of gradle trampling upon maven. before starting considerations along the lines "this software does not do X" or "it does X wrong," what about asking "what's a reasonable task for a single tool?" or more specifically,
"do we really want dependency management and builds handled by the same program?" my impulse is always to go for things that are as modular as possible, but perhaps the reflex response of "no" isn't correct for some reason obscured by lack of experience with the particular problem domain.
Ivy is "only" a dependency manager, you can't build stuff with it. Gradle was originally based on Ivy but they decided to roll their own Ivy/Maven compatible dependency engine.
Gradle is a very powerful engine: we use it not only to build Java/Scala/Groovy code but also to drive our continuous integration/deployment cycle.
Again, it obviously depends on your requirements, but if you have to deal with large and complex projects, with lots of submodules to build, do consider Gradle.
> but they decided to roll their own Ivy/Maven compatible dependency engine.
I'd heard about that...as a non-Gradle Ivy user, when they started this, I asked two of their devs if they were going to basically write an "Ivy v2", submit their improvements/patches back to Ivy, etc.
Their response was, paraphrased, "absolutely not, we're building our own thing that is way more awesome and are not interesting in sharing". Which I found disappointing.
I know a clean break is easier, and that the Ivy codebase likely needs it, but Ivy could really have used their focus, and I think it would have benefited the wider Java ecosystem (as many non-Maven builds use Ivy to talk to Maven repos) instead of just Gradle itself.
havent had a problem ivy and ant didn't tackle relatively gracefully yet. I'm only using gradle because all the cool kids are but tbh I'm not really a fan of groovy. I wouldn't ever use the language outside of gradle and thats a bad sign to me.
I looked at all these tools... Then carried on using Makefiles. Seriously, people, building has been a solved problem for decades. Let's all stop fooling around and concentrate on actually writing code!
Well, I use VIM to write Java/Scala/Groovy/Python code but unfortunately large, complex projects do exists and the java ecosystem is particularly good at making things more complex that they need to be.
A reliable, flexible and built on sane principles build system is required when dealing with large enterprisey projects.
I don't mean how do you version a Makefile, but if your project depends on 6 libraries (with various version requirements) each with their own sets of dependencies, how do you use Makefiles to download & install all of them?
It depends. For tracking released versions, just let the Makefile download (wget,tar) and build (./configure,$(MAKE)) it. For tracking repo revisions use the VCS (git-submodule,git-subtree).
Ah, I see. Well I don't get involved in projects as Rube Goldberg as that. The 3rd party libraries I rely on have stable interfaces, and current-version is always preferable.
Oh right, then yeah Makefiles are the way to go :)
I'm not sure I'd call those things Rube Goldberg, it's just about depending on small libraries and having a reproducible build if it gets checked out on a CI machine and run.
As always, all about choosing the right tool for the job. If you can solve it cleanly with something simpler then you probably should. Something like Maven should only be used if you're really sure you actually need it, because otherwise it'll be a pain in the arse.
Having said that, splitting up "building" and "dependency management" can make things much simpler. Pip (python dependency manager) is incredibly simple, with the same kind of interface as apt, and if you've got a file with a list of dependencies you just tell it to install all of those. Then you can use whatever you want for the build process itself.
The "this is code but you have to write it as correctly-formed XML" bit is whacky. OTOH, as syntax goes, it probably beats syntactically-significant varieties of whitespace.
> The "this is code but you have to write it as correctly-formed XML" bit is whacky.
that's all over the java ecosystem, though, not just build tools: android and (i think?) spring both use several types of xml files to build. not saying it's not whacky, but it's def. prevalent.
In the Tools category, Gradle is "Adobt", while Maven is on "Hold". You can read the full report but I'll exert the relevant section:
"Language-based build tools like Gradle and Rake continue to offer finer-grained abstractions and more flexibility long term than XML and plug-in based tools like Ant and Maven. This allows them to grow gracefully as projects become more complex."
They had a more elaborate explanation in previous editions.
In many enterprises we work for, Maven is still in the "to adopt" phase.
Having said this, I am also an Ant guy for simple projects. Too many scars from an Ant -> Maven migration. All pom.xml files ended up more complex than the original build.xml files, as Maven did not have proper support for the way the build was working before.
Ironically the biggest pain with Ivy is that 99% of your dependencies will be pulled in from Maven oriented sources, so you still have to deal with Maven's deficiencies around dependency configurations.
No, everyone is not moving to Gradle. Gradle is Ant in Groovy clothing. If you want incomprehensible build files ala Ant, choose Gradle. If you want standard build files and a rich ecosystem, choose Maven.
Gradle's purpose is to muscle in on the consulting / conference market for Ant, just as Grails's purpose as wrapper around Spring and Hibernate was initially to muscle in on their consulting businesses. Now they've hooked in enough users, their bait and switch business strategy is now to screw them for as much money as they can.
So if you use Gradle now, you'll pay the cost later on after Gradleware is sold to some GE or VMWare or EDS or Oracle.
Yeah, no. Gradle is really nothing like Ant. A bad build script author can use it to write build scrips that look like Ant with curly brackets, but then you can write COBOL in any language. If you take the ten minutes to learn how Gradle actually works, then you don't end up with scripts that are like Ant.
Advocating Maven over Gradle is just a joke. I routinely do things in Gradle scripts that would require writing an whole new plugin to do in Maven.
Even for strict java builds, I've been using 'sbt' (the Scala Build Tool). It really is the successor to gradle, in many regards. Not sure you've tried it as one of your alternatives, but I'd implore you to give it a try.
Ant user here. Ant is Turing-complete, which serves as an object lesson in "can" versus "should". I have actually had cause to program in Ant - because that was the right place for the complexity in question - and would characterise it as what COBOL would look like written as correctly-formed XML. Oh the verbosity!
To be fair, I'm doing things that are actually bad and wrong. (At which point ant-contrib is your last friend.) Ant does its actual job - makefiles for Java - pretty well once you know it. It's fine, y'know, probably pretty much complete.
Here's Netflix Exhibitor (which I wrote): https://github.com/Netflix/exhibitor - the developer who wrote the build scripts did an incredible job. I'm very impressed. However, I don't comprehend it. Note: this was previously in Maven and had exactly 3 POM files.
To my eyes, the build scripts are pretty clear. I like the way the scripts are nicely organized using 'apply'. Maybe the only script that may look complex to someone starting with gradle is 'convention.gradle', but again, nothing impossibly hard to grasp for a developer.
I am not able to maintain these build scripts. This is the problem with DSLs in general. Maven isn't great, but its strength is standardization. I can look at any Maven pom and know what it does and make changes to it.
I'm a sw engineer programming Java since 1996. I started using Maven when it first came out as the declarative build language hooked me, and became the local Maven expert. I've watched it grow with pride, and sometimes in anger. I still believe a declarative build language is best, but it won't be in XML. I suspect it will eventually be in something like OWL, whatever comes along after OWL that fixes its issues.
So as of a few years ago I too moved on to Gradle and have loved it.
But...
Language based build systems offer more expressiveness, but that is also more rope to hang yourself with if you get someone that doesn't know Gradle well doing tinkering with your build. For example we had someone add a custom checkstyle report to an Android project using Gradle. After their edits it stopped working because of the way the Android plugin was designed, bringing the build down for several hours. I came in, rewrote the Gradle build file to workaround the issue and it worked. Then I documented to the person why it hadn't worked and what I did to fix it.
As with the adoption of anything that gives you more rope to hang yourself with, it's a necessary piece of Gradle adoption to document your practices and train your team well.
Incremental builds: I am working at a Java shop at the moment and was amazed to find that even the resident Maven experts clean before every build. To me incremental builds are one of the most important functions of a build system, but it seems that users of Maven and other well-known build systems used in the Java world have given up on it because it just doesn't work. So anything which fixes even only this problem would be a step in the right direction.
I read how TeamCity did their incremental builds and wrote my own script. I drop an anchor, detect changed files and then build up a list of modules that need to be rebuilt. I then tell maven to build those modules and their downstream dependencies.
One thing which I detest about maven, it uses http by default. Getting it to use https requires a lot of work[1] so many don't use it.
By default, not only are you downloading a truck load of jars from the internet and running them locally, you are fetching them over an insecure channel!
What is HTTPS supposed to protect against in this case?
1) If you are using it to protect against snooping (why?!) then you must realise that the logs of many Maven repositories are effectively public (eg, I believe Apache committers can access the repo.maven logs pretty easily). For protection against snooping, use a local repo.
2) If you are expecting it to protect you against tampering in transport, then you are better off using a local repo (again). It's much more likely artifacts are tampered with at the remote repository rather than during the transport phase.
It's much more likely artifacts are tampered with at the remote repository rather than during the transport phase.
MITMing the public wifi at some coffee store is much easier than breaking into the official Maven repositories. At least I hope so. That's why RPM and DPKG packages are signed.
Ok, but the impact of hacking the official repo, vs sitting at some coffee store hoping someone in the same coffee store builds a project using a particular lib you have code to modify on the fly while you mitm that exact repo pull?
He said much more likely the repo is tampered with. Easy to see why. This coffee shop scenario, they'd have to be targeting you personally and know your habits and your build and code they need to target you. In which case, https is far from your biggest concern.
Replace "coffee shop" by "software conference hall" and "specific lib" by "current log4j/junit/whatever very common library you want".
Suddenly it's a lot less targeted attack. Moreover, the "victims" should be of much higher profile than your regular student downloading an obscure library whose repo you managed to hack.
Not that I think it's a particularly important security concern. However, when you are dealing with security concerns, the fact that you can't make up a situation that sounds bad enough doesn't mean that nobody else can't.
Update: sorry for the wording of the last sentence (non-native speaker here). I'll be glad if someone can correct it, because I can't figure out how to construct it to sound well.
It's for when you trust the public repo operator, you trust the authors of the package you're downloading, you trust your local machine, you trust the repo operator's SSL CA, but you don't trust the connection from your computer to the public repo.
https is useless for package management, given that most people are downloading from mirrors. What you want is a signature over the entire repository, like Debian and Ubuntu do (not just signing individual packages, like Fedora does). Once you have that, you don't need HTTPS.
> a pom.xml can only list a single source folder. If you have more than one (for whichever reason)
I agree that this example demonstrates that the Maven model is broken, but why would you structure your project like this rather than using another module or a submodule?
Maybe it's just lack of experience, but I highly prefer the rigidity of Maven projects compared to some of the messes that more expressive build systems allow.
That's fine, so long as the problem you're trying to solve is easily expressed within Maven's structure.
And sometimes, expressing it withing Maven's structure can lead to very slow builds, at least within my experience.
But perhaps I'm prejudiced; I hate maven, and have since my first experience with the Mvn 2 betas. You know when you see a new technology and you say, "this is painful now, but it's going to be worth it in the end?" I got the "this is painful now, and is only going to get worse as plugins depend on crazy ass behavior" feeling.
Please substantiate this, as I've been using Maven for quite a while and while it isn't perfect, it's not remotely painful. And I'm not talking about just for "build this jar" projects; most of my Android apps use Maven, too, as do a number of projects of mine that have native dependencies.
(I have no problem with Gradle, either; I just generally find most of the Maven complaining to be overblown.)
Luckily, these days I don't have to work with Maven. :) - But that means I don't have any current Maven code I can distill out as examples. However, I think the blog post does a good job of laying out these problems, particularly the way that incremental compilation sucks in Maven. One example used to be some major issues we had with jasper reports. We had xml files that weren't really jars, that needed to be in a particular directory within the parent war, and had different XML files to use for different clients. So it wasn't as simple as one input, one output. Some files were shared for certain clients, some were client specific. Sometimes we depended on two different files -- one client might have one report1.xml, another client would have a different report1.xml.
This is actually pretty simple with Ant, but becomes a nightmare trying to fit into a Maven structure.
Gotcha, thanks for the response. I think a lot of why Maven doesn't bug me is because I'm not really an "enterprisey" Java/Scala guy, I use it to build more discrete and contained stuff. I had to look up what JasperReports was. :-P But I use it for libgdx projects, for Android stuff, and for just quick one-offs without a hitch. Before Play (which uses SBT, which I'm not thrilled about, but, anyway...) came around I strictly used embedded Jetty--I'd use Dropwizard these days if I was to do that with Maven again, it's great.
I've tried on many occasions to make Maven work with Eclipse but Maven nearly always finds a way to mess up Eclipse's excellent project management abilities. I'd say that if you just write code in an editor then Maven makes a lot of sense, if you use a powerful IDE like Eclipse then Maven becomes an unwieldy and unnecessary challenge.
I am not very experienced in using Maven, but the biggest problem I have with it is, that it is hard to tell (at least for my level of experience) from where dependencies are pulled. Is it my local mirror, is it something on a central nexus in the company or is it totally from outside?
Build reproducibility, which the author mentions is another issue. When I scrub the local mirror, the outcome can be completely different. Previously builds where working fine, when I scrub, everything breaks. This is mainly due to non-local dependencies which had been cached locally, but not replaced by most recent versions.
Another suspicion I have is that most build scripts are slapped together by googling until it works. Which of course is prone to being fragile (not to mention legal issues because it is opaque from where all stuff is pulled).
Never, ever, ever add any repositories to your pom.xml. Never. Have one central repo (nexus, artifactory, whatever) for your organization and make it a mirror of all others via settings.xml, not in the pom. This adds a lot to build stability and reproducibility.
+1 for buildr. It admittedly takes awhile to learn the DSL, but it seems like all of these DSL build tools take awhile to learn.
(I think that was one really nice thing about Ant--you could scan their manual/list of tasks and understand it very quickly.)
It seems a little odd using Ruby to build Java projects, but ironically I actually prefer that over Groovy.
This is horrible for me to say, but I'd like Groovy to gracefully go away--it lost the Java.next race (they were stubborn about dynamic typing for way too long) and I feel the only reason it's still around are for the admittedly nice frameworks it sprouted: Grails and Gradle.
The language itself is "meh", IMO.
...although it bothers me to no end that a dynamic language like Groovy had compile-time AST translation way before other (similarly mainstream) static languages like Scala.
Anyway. Gradle's momentum is impressive. Perhaps I can unlearn my Groovy bias.
It might be, but it still has it's merits. It was one of the first, and many other improved tools can't work without it's repositories.
I still like the IDE support for MVN: e.g. IntelliJ draws a nice dependency diagram that I find useful, even if I don't use Maven for something else in a project.
Maybe it's biggest mistake was that dependencies are global by default, and not local (like Node's NPM). If the dependency structure would have been local to a project, than many of the pain points I encountered with MVN in the past wouldn't have even existed.
> Maybe it's biggest mistake was that dependencies are global by default, and not local (like Node's NPM). If the dependency structure would have been local to a project, than many of the pain points I encountered with MVN in the past wouldn't have even existed.
I don't understand the local vs global dependency thing. What does NPM do differently from Maven?
> I don't understand the local vs global dependency thing. What does NPM do differently from Maven?
As others have pointed out, NPM as a default is using "local" dependencies, (something I couldn't achieve with Maven easily).
"Local" means that the dependencies are in a sub-directory of the project, and that the transient dependencies are in sub-sub-directories too if needed.
With NPM, for us some of the implications of this are the following:
- being "self contained" I can check in a VCS and tag it "completely" or just zip it and send somewhere else, where it can be built "as it is", even on CI machines or production machines that have no Internet connection, nor do require a company internal Maven server.
- bugs and issues with building are reproducible. The "it builds on my machine" doesn't happen anymore. (Just search the different Apache mailing lists of how often this happened even in those open source projects). We had this problem very very often - to the point where several projects were migrated to ANT again.
- the availability of public Maven Repos, their mirrors and their sync is just bad (sometimes it's the corporate firewall/proxy the problem), so builds just fail all to often. Many companies don't use internal Maven Repo Mirror
- none where I worked had one, nor could we convince the management to finance one.
- very often (even visible in open source projects that build with Maven), there are some dependencies (maybe not from the start of the project, or maybe only temporarily) that are not available in the official repos, so need to be manually added. Doing this in a sub-directory is much easier, and it needs to be done only once, so others will just use it.
These are just a few issues that NPM seems to have been solved nicely (or just not having them because of of the "local" defaults).
Of course, there are also disadvantages of this "local" approach (like the redundant disk space usage - where the global one is very efficient), but from my experience all these disadvantages pale compared to the problems and frustration Maven brought in many projects that adopted it.
Maven stores all of the artifacts that it retrieves in one big local cache so that you don't have to pull the same dependency down.
NPM, by default, will store the artifacts into a directory local to your project.
The maven way sounds nice, but it's easy to possible to screw things up between different projects. (Especially if you have mvn 2 and mvn 3 projects, ugh).
With NPM, everything is nice and separated.
Ivy is like a mix of the two (a global local cache, but pulls down to the local project), which IMHO, has the benefit of neither while getting the drawbacks of both.
How is it easy to screw things up? You specify the version of a dependency when you write each POM file. If there are two projects, each with different dependency versions, they only get the dependency version they requested. Only if you have two different dependencies that report themselves as having the same Maven coordinate, that is to say the same Group Id, Artifact Id, and Version number, will you have any problems. But then that isn't a "Maven" problem insomuch as it is a bad dependency.
NPM stores dependencies in a node_modules folder within the project directory, i.e. "locally." It does have a command-line flag to store something globally, though -- useful for dependencies with executables.
I'm not a Java developer but it sounds like Maven stores all its dependencies globally (like in /usr/share/java). I'm not sure why that would be a "pain point" except making it hard to do different versions of the same library.
Maven stores dependencies in ~/.m2/repository (so "globally" per user). However, it can and does store parallel versions of the same library without issue. It's not much of an issue unless you need to copy your source folder elsewhere, in which case you either need to copy your .m2 (with stuff from all your various projects) or wait until maven re-downloads everything.
Except that you request the dependency version you need for each module. Since the classloader can't load different versions of a dependency, it makes sense to unify the version across the application, and that is easily done with a Parent POM. If you are using OSGI to keep modules isolated when the classloader loads them, then you can request whatever version you want for a particular module.
i might be mis-interpreting your local vs global dependencies, but if you are wary of the network nature of maven, you can always check into your scm the maven repository (and perhaps, pre-fill it with just the deps needed).
Any tool can get hold of the full state of how to build the project, then interpret it itself, rather than having to work out what the imperative code is trying to achieve.
Running joke in my office: whenever you waste a day on some trivial task because you had to edit some stupid XML config file, you lose a sanity point.
I have learned the hard way to read some of the source code of any external library or tool, no matter how widely accepted, in case the person who wrote it didn't attend the class on not using global variables or depending on undocumented internals of the JVM (I'm looking at you Log4j 2). Or in case they were just plain bonkers, like everyone who was involved in writing Spring.
I wouldn't call it the "Java" philosophy. Rather, I would call it the "wet behind the ears" philosophy. It just so happens that they correlate because of the way people are trained.
To suggest that this is an effect of the language rather than various teams of different people building different tools at various points in times seems silly.
What other language hasn't had multiple build solutions that were each "the one solution" at some point in time, only to be supplanted later?
How many build solutions are there for C++, or Ruby?
I don't think there is an actual maven IDE. You normally use it from the command line, since it's integration into IDEs is serverly (eclipse...) lacking.
I'm the only developer in my shop using IntelliJ. Everyone else uses NetBeans. Whenever someone asks me how to setup NetBeans to handle builds as easily as I do, I have to shrug. Simple things, like switching to offline mode or turning off tests is a chore for NetBeans, but it is just a simple button click for me. If I want to target a specific build profile, I check a check box.
As I'm the one who maintains the build, configuring pom.xml files and setting up modules, I can see how it can become difficult for someone who doesn't have the experience I do. OTOH, I've yet to find a problem that stumps me when I'm doing things the Maven way, and I rather enjoy the flexibility and power it provides me. Once I've got the basics in place, maintaining the system is almost trivial.
I don't use maven for my builds these days but that's completely wrong. configuring deps is painless as is adding plugins. I've used it to build maven projs as well as osgi projs.
I have been using Gradle now for almost 3 years and I can't be happier. The support is great, they roll out new features at a regular pace, it's fast and incremental build WORKS.
If you work in Java and you are still stuck with Maven, please, take a look at Gradle.