Maven builds are an infinite cycle of despair
kent.spillner.org
kent.spillner.org
1. It is very difficult to configure a hermetic Maven build that doesn't rely on external resources. There are third-party repository managers, but none of them worked well enough to replace the 'dependencies in SVN' model.
2. Maven artifacts were often far out of date. RedHat has its own Hibernate-focused repository now, but this wasn't always the case. I'd find myself trying to get the latest version of dbcp or another commons project to get a bugfix and finding that it wasn't packaged.
3. Support for multiple source-based projects that depend on each other felt bolted on. I can't remember the details, but you couldn't build more than one project from source without specifying a link to a parent project from each child project, which then referenced each of its children.
I've written and rewritten countless build systems (from batch files last millenium to Ant/NAnt/MSBuild) and they always end up being simple wrappers over javac/junit that manage transitive dependencies and build cycle ordering. The tricky part is ensuring that your IDE's dependencies match those in your build system.
I recommend Ivy as an alternative to straight Ant or Maven that does dependencies and ordering well, but doesn't require you to buy in to any special build philosophy: http://ant.apache.org/ivy/
Quick addendum: Ivy has its own quirks and is far too complex under the hood for my taste, but does the job well if you stick to straight dependency management. If you can avoid using anything on top of pure Ant scripts to build your project it'll make your life way easier.
If you use it right you end up with 1 source of truth for your build. Most Java IDEs support maven as a project model, and therefore you don't have to maintain two separate builds: one for the IDE and one for the build system--something that always leads to integration pain.
Ant as a tool isn't capable of this, since it doesn't really represent an project object model. Certainly IDEs can invoke Ant targets, but their non-standard nature make tight integration with the IDE hard, if not impossible.
There are several things that Maven could do to make the experience better. I suspect many of them will be addressed in 3.0; however, Maven as an experience has always sucked and I suspect will always suck. The broad based acceptance of the tool will give it a certain inertia that is likely going to be hard to overcome.
For me, the M2 plugin for Eclipse seals the deal as it makes the build files double as the IDE project files. One place for dependencies, one build cycle, this is how things should be.
I hate Maven with a passion, and use Ant any chance I get, but for very large multi-module projects, the strong points outweigh the negatives (although by an uncomfortably slim margin).
Breadth vs Depth I suppose.
"No knowledge of Ruby is assumed. Buildr is designed to be a very intuitive, very easy-to-use tool. You can create buildfiles which describe incredibly intricate projects, write custom tasks which do things far beyond Ant, and still never need to pick up more than a smattering of Ruby syntax."
Also, learning a new programming language isn't exactly a waste of time. When I learned Ruby it made me a far better Java programmer, for instance.
While I'm learning Ruby, it did not make me a better Java programmer. I still suck at Java programming.
Reading books like Code Complete, Pragmatic Programmer, Clean Code, and reading Zen of Python (import this) help me to become a better programmer; but learning Python does not help me to become a better developer. Reading better code (other people's or projects's) do make me know more.
I finally understand what does it mean with the phrase "no matter what they tell you, it's always a people problem.". Languages have nothing to do with it.
Yes, learning a new language can and does make you a better programmer if it introduces new concepts you can apply to other languages.
* slow (even with -o to stop it downloading the internet every time)
* incredibly verbose, in both configuration and output during builds
* inflexible (but I've not really looked into plugins or advanced configuration)
* opaque and thinly documented even for basic needs
I did a fair amount with ant a few years ago and found it a much more pleasant experience. Maven seems to me stereotypical "enterprisey" software: a mediocre, moderately complex solution to an extremely complex problem.
"slow" - can't say I've found that an issue when compared with Ant which I used to use.
"verbose" - in configuration I disagree - the more you put in your pom the less well you're using it. In output true, but I'm not sure why that's intrinsically a problem for you.
"inflexible" - absolutely not true. You can configure a plugin and Maven will go and download it for you - so as a user you can enhance the tool directly from the configuration file (e.g. I typically use a plugin to build database scripts from annotated classes).
"opaque" - yes, but there's method in that madness. It's programming by exception (how is my project different from the default?") as opposed to Ant's (mainly) explicit programming ("How exactly is this build bootstrapped?") Once you know the pro forma you can jump into any Maven project with an immediate understanding of its likely structure - very different from Ant where you basically need to read the build.xml files to know where everything lives.
"thinly documented" - Yep. The documentation is horrible and that's its biggest problem in my opinion.
It standardizes the layout for the majority of java based projects.
It also lets me deal with dependencies in a decent manner. Maven should not be downloading dependencies on every build unless you are using SNAPSHOT versions.
There is a free book available: http://www.sonatype.com/products/maven/documentation/book-de...
(I know Maven doesn't actually redownload everything each time, but it does seem to do something on the internet every time I build without -o; and even with -o, it still seems slow to get going. Might be project-specific / PEBCAK error though.)
When I'm justifying including a third party (open source) library I ignore those that are not build with Maven and whose artifacts are not installed in the central repository.
* slow (even with -o to stop it downloading the internet every time)
At least you don't have to download everything manually, which is far, far more tedious. I'd rather let it to the tool to download dependencies.
* incredibly verbose, in both configuration and output during builds
I bet the simplest pom file will be shorter than the equal ant build script. And I personally don't care about output verbosity.
* inflexible (but I've not really looked into plugins or advanced configuration)
You can easily extend maven builds with ant scripts, which makes Maven as flexible as Ant.
*opaque and thinly documented even for basic needs
That may be the real issue.
Maven has a learning curve -- although it isn't huge. It can be frustrating sometimes, but if done right, it has so many advantages over other tools. There are free online books on the topic.
Project A has the source in /java/src Project B has the source in /main/src/java Project C has the source split in two different dirs: /src/test/java /src/main/java
worse yet, compile targets are called: project A -> compile project B -> build (note, the build target in project A will deploy the software to a stage server... good luck the first time you accidentally figure that out) project C -> go
and to maintain the version number of your package: Project A uses a file called /resources/projectA.properties with a key of "verno" Project B uses a file called /main/project.version Project C uses a property set in /build/build.properties
Maven, when used in a way to avoid the above mentioned problems, will typically have the source code structured the same way for every project.
Yes, it's java-centric yes, configuration can be a mess yes, documentation is redunkuluously poor
But it sure beats wracking your brain trying to figure out how to build a project when every new developer does it a different way.
PS. I've never experienced any of the performance/download problems other folks have mentioned. I think they might be doing something wrong.
But that said, Maven has a build tool absolutely fucking sucks.. I much much prefer ant, and totally agree that mvn can be completely retarded and suck away a half day randomly.
If there was an ant alternative to deal with the library dependency problem then I'd be all for it. It seems that now that ibiblio exists, there should be ample opportunity to do this, basically rewrite mvn but use the existing repos.
But really, this single command makes mvn worth the trouble for me: % mvn -DdownloadSources=true -DdownloadJavadocs=true eclipse::eclipse
Give me another tool that does the same thing by me just specifying all my direct dependencies and version numbers and we can talk.
-Nic
1) The Maven Ant tasks: http://maven.apache.org/ant-tasks/index.html 2) Ivy (now part of the Ant project): http://ant.apache.org/ivy/
We use Ant+Ivy, and although it has some quirks Ivy works well enough for dependencies.
As I said, that is the one big carrot still keeping me in mvn camp.
Ivy is mainly a tool to work with ant, so it makes some sense that IDE integration is not in the same project, but as far as I could see, ivy and the eclipse plugin are written by the same people.
The eclipse plugin was actually one of the reasons for choosing ivy over maven, because at the time maven was moving to 2.0 and its eclipse plugin was not yet available or stable. The other reason was the documentation. At the time there seemed to be more documentation about ivy than about all functionalities of maven together.
If that doesn't set off just about every warning bell in your head, consider that Ant performs character set decoding and re-encoding when copying files. By default it will decode every file with your system's default character encoding and then re-encode it with the very same format. As far as I can tell all this can possibly do is introduce errors. When copying a binary file the best-case scenario is that your JVM throws a runtime error, but it's more likely that ant will silently corrupt the copy.
The Ant team's solution for this problem? You might reasonably expect that they would provide an option for binary files which does a byte by byte copy. Instead they suggest that you change an environment variable to an encoding which "does not seem to contain illegal character sequences."
Maven is declarative, not imperative.
Ant is broken in many respects, but your provided example is not true. Ant only attempts re-encoding of a file if you specify text filters (aka variable/string replacement). It shouldn't be a surprise to anyone that string replacement breaks on binary files.
1) try maven but don't bother to RTFM 2) run away with your hair on fire and back to cave-man tools like Make, Rake & Ant 3) ignore dependency management 4) re-invent the build script for _EVERY_ project you start. 5) ??? 6) profit!!!
You only ever hear rants like this from people who don't spend the time to learn maven. It's not that hard. This is just rants.
It sounds like he chose to just give up on the tool, spend a lot of time ranting about it on a blog, and go back to what he was familiar with.
Most Maven users are "forced" to use it when they join a company or a project; they did not pick up Maven and learn it on their own time.
So far, I haven't had much trouble with Maven. I've only done fairly straightforward web programming, with Spring, Struts 2, and Hibernate. It was a hassle to get it all set up, but I blame Spring for that, not Maven. The conventions seem to work very well, since you can just follow a standard directory structure.
I've found it particularly easy to use mvn war:war to create a war file, which is why I wish the author had elaborated a bit on why he needed to "reconfigure the conventions".
I have no argument with the author's preference for rake (and rails, for that matter), which is a far more pleasant environment than maven, spring, struts 2 (or something else), and hibernate, but of all this, Maven (I'm talking about Maven 2 here) was by far the most pleasant part of the stack for me.
One last thing - I promise I'm not being glib, feigning misunderstanding where I actually disagree. I'm pretty sure the author is a good programmer who has a legitimate gripe, and all I've done is basic CRUD programming with the stack I mentioned... but I definitely would like to hear some details.
- very handy when starting new projects - easy to generate project files for Idea, Eclipse etc.
I used ant in the past, maybe it is more flexible, but also requires more work to set up initial build file. I find Maven just easier to use.
What I liked the most is consistency across project files, project structure.
This. You need to be able to check in your build tools, and use them as they were to precisely repeat any build you've ever done, or you're risking bit rot. Ant is sort of painful but it works for this.
And if I want my dependencies to be preinstalled rather than checked in and bundled, I'd rather use yum so the rest of the world can reuse them too. Does Maven even support dependencies upon native (non-JVM) apps and libraries which are available for a given platform?
It's not non-deterministic if your dependencies include an explicit version. You should not be using unversioned -SNAPSHOT dependencies for release builds.
And if I want my dependencies to be preinstalled rather than checked in and bundled, I'd rather use yum so the rest of the world can reuse them too. Does Maven even support dependencies upon native (non-JVM) apps and libraries which are available for a given platform?
No. Maven is intended to support easy-to-use bundled code dependencies, not to operate as a complete replacement UNIX packaging system.
Also, you didn't address the gp's complaint that the build tool will spontaneously update not only the project dependencies, but also itself. Some maven plugin developer out there can release a new version, and a project that compiled fine yesterday suddenly won't compile anymore. I'm sure there's a way to force it to use particular versions of the plugins as well, but by the time you explicitly list every transitive dependency and every plugin used in every phase of the lifecycle, you've got a really big configuration file, especially for a tool whose motto is "convention over configuration." Not to mention that if you accidentally forget to specify a version number for one of these potentially dozens of packages, maven will happily default to using the latest version, which makes your build secretly nondeterministic.
1) You absolutely should have your own local repository (e.g. Archiva). 2) You should use <dependencyManagement> and <pluginManagement> tags to force all projects to have the same versions o all deps and plugins. 3) Don't even try using snapshots unless you know what you are doing.
No.
... if you want your build to be deterministic, and of course you do, you still have to specify bar and baz explicitly
If you declare a dependency on non-snapshot foo, then it will also declare a dependency on non-snapshot bar, ergo, reproducible build.
Your comments seem to be the standard "I don't understand Maven, but I hear that it's broken."
> the far more likely scenario is your project depends on a specific version of some other project which in turn depends on the LATEST version of some other project, so you still get hosed even when downstream providers do remember to bump versions!
so are you saying this is impossible (non-snapshot artifacts are somehow forbidden from depending on snapshot artifacts, which is not what was claimed), or that every author has to understand this and package their artifacts perfectly to prevent this from becoming an actual problem?
Take a look at how to configure settings.xml to force your users to use only your local repo.
As far as <dependencyManagement> tags -- the point of that is to hard-code the version of foo in one spot, like this:
<dependencyManagement> <dependency> <groupId>com.example</groupId> <artifactId>foo</artifacatId> <version>1.1</version> <dependency> </dependencyManagement>
In child pom, you then have this if you need foo:
<dependency> <groupId>com.example</groupId> <artifactId>foo</artifactId> </depdendency>
And if you use something like Archiva, and force your users through it via settings.xml, then the first time someone downloads foo, Archiva gets it from the web, caches it, all other requests for foo go to Archiva. If foo has a transitive dependency, it will also get fetched from the web one time and cached in Archiva. Thus, guaranteeing that your build is deterministic -- unless you explicitly change foo/bar in Archiva yourself.
The attractive part of maven is that it manages all the version dependencies for a large development team. For a solo developer it is way too much pain.
I replaced maven by ant+RPM+yum+Hudson in one large project, and everybody is happy.