Advice on a good Java build tool, well integrated with eclipse - java

I am working in a small team (3 persons) on several modules (about 10 currently). The compilation, integration and management of build versions is becoming more and more tedious.
I am looking for a good build / integration tool to replace / complete Ant.
Here is the description of our current development environment :
- Several modules depending on each over and on third party JARs
- Some may export JARS, some export WARS, some export standalone, runnable JARS (with Fat-Jar)
- Javadoc for all of them
- We work with eclipse
- Custom Ant script for each module. Many redundant information between the eclipse configuration and Ant scripts. For example, for the standalone Fat-JAR, we have listed all the recursive dependencies, whereas ideally, it could clearly be imported from the eclipse configuration.
- The source code is versioned using SVN
Here is what I would like a perfect integration tool to do for me :
Automatize the releases and versioning of modules. Ideally, the integration tool should detect if a new version is needed. For example, if I want to release a project A that depends on a project B, and if I have made small changes on the project B locally, then the integration tool should first release a new version of B as well and make A based on it.
Integrate strongly with eclipse, so that it could get the dependencies between modules and third party libs from its configuration. BTW, I would like to continue to configure build path with eclipse without updating some other ".xml" stuff. I saw that Gradle can generate eclipse project files from its configuration, but the counterpart would be great.
Enable a "live" and transparent development on local projects. I mean that I often make small changes on the core / common projects while developing the main / "leaf" projects. I would like to have my changes on core projects immediately available to leaf projects without the need of publishing (even locally) the JARs of my core projects.
Store all versions of the releases of my module on an external server. The simplest (shares folder / Webdav) would be the best. A nice web page with list of modules and delivered artifacts would be great too.
I have looked around for many things. From Ant4eclipse (to integrate the Eclipse configuration into my Ant script), to the Maven / Ivy / Gradle tools.
I am a bit confused.
Here is what I have understood so far:
- Maven is a great / big tool, but is somewhat rigid and obliges you to bend to its structure and concepts. It is based on description rather than on scripting. If you go out of the path, you have to develop you own plugins.
- Ivy is less powerful than maven, it handles less stuff but is more flexible.
- Gradle is in-between. It is general purpose. It enables scripting as well as "convention based" configuration. It integrates Ant and extends it.
So at this point I am looking for actual testimonials from real users.
What tools do you use ? How ? Do you have the same needs as me ?
Does it ease your life or get into the way ?
Are there sample some use cases, or workspace skeletons out there that I could use as a starting point to see what these tools are capable of ?
Sorry for the length of this message.
And thanks in advance for you advice.
Kind regards,
Raphael

Automatize the releases and versioning of modules (...)
The concepts of versioning and repository are built-in with Maven and they could fit here.
Maven supports SNAPSHOT dependencies. When using a snapshot, Maven will periodically try to download the latest available snapshot from a repository when you run a build. SNAPSHOT are typically used when a project is under active development.
Maven 2 also supports version ranges (I do not really recommend them but that's another story) which allow for example to configure A to depend on version [4.0,) of B (any version greater than or equal to 4.0). If you build and release a new version of B, A would use it.
Integrate strongly with eclipse
The m2eclipse plugin provides bi-directional synchronization with Eclipse.
Enable a "live" and transparent development on local projects.
The m2eclipse plugin supports "workspace resolution": if project A depend on project B and if project B is in the workspace, you can configure A to depend on B sources and not on B.jar (that's the default mode if I'm not wrong). So a change on B sources would be directly visible, without the need to build B.jar.
Store all versions of the releases of my module on an external server.
As mentioned earlier, this is actually a central concept of Maven (you don't even have the choice) and deploying through file:// or dav:// are both supported.
To sum up, Maven is (probably) not the only candidate but I'm sure it would fit:
Your project isn't that exotic or complex, there is nothing scaring from your description (some refactoring of the structure will probably be required but this shouldn't be a big deal).
Maven also brings a workflow based on best practices.
m2eclipse provides strong integration with the IDE.
But Maven has some learning curve.

CI tools? To me, there's only one: the Hudson CI.
I've setup a software development environment for Java once, with the components:
eclipse IDE
mercurial
bugzilla
maven
Nexus
Hudson CI
and some apache, mysql, php, perl, python, .. for integration.
The hudson was not integrated with eclipse and that was on purpose, because I wanted to build on a separate server. for all the other tools I had a perfect cross integration (like: mylyn on eclipse to talk with bugzilla, m2eclipse for using maven eclipse, a lot of plugins for hudson, ...)

We've been starting to integrate Gradle into our build process, and I can add to the answers posted already that Gradle would also work. Your assumptions are mostly correct, gradle is more off the cuff, but is powerful and allows for scripting and such within the build itself. It seems that most things maven can do, gradle does as well.
Now for your individual points:
Versioning: gradle supports dependency maps, versioning, and if you add in a CI server, you can trigger automated/dependent builds. For example, almost all of our 'deliverables' are .wars, but we have several code libs (.jars) and one executable .jar in development. One configuration is to make the the wars and the "fat-jar" dependent on the shared code libs. Then, when the shared libs are updated, bump the versions on the shared libs, test the consuming projects, then use Hudson's ability to fire dependent projects to redeploy those. There are other ways, but that seems to work best for us, for now.
Integrate strongly with eclipse: You're right, gradle can generate the eclipse files. We tend to only use the eclipseCp (to update .classpath) task once we get going, as only classpath needs changed. It's kind of quirky (grabs your default JRE, so make sure it's right, doesn't add exported="true" if you need it), but gets you 99% of the way there.
Enable a "live" and transparent development on local projects: This is one I'm not sure about. I've only hacked around gradle in this case; by removing the artifact in the consuming project and marked the shared project as such in eclipse, then reverted afterwards.
Store all versions of the releases of my module on an external server: simple and many approaches are supported, similar to Maven.
As far as examples, the docs for gradle are good, as well as the example projects that come with the full zip. They'll get you up and running fairly quickly.

Have a look at Ant Ivy. http://ant.apache.org/ivy/

There are no silver bullets, but in my experience Maven is a great project management tool. Personally, I like to use a comibnation of subversion (for version control), maven (for project/build management) and hudson (for continuous build/integration).
I find the convention brought by maven is really useful for context switching, and great for dependency management. It can be frustrating if jars aren't in the repositories, but you can install them locally and when you're ready you can host your own private repository which mirrors other places. I have had a good experience using sonar.nexus by http://www.sonatype.com/ . They also provide an excellenmt free book to get you started.
It might seem like overkill now, but setting up a good build / test / integrate / release environment now, will pay dividends later. It's is always harder to retro-fit, and it's something you can replicate easily.
Lastly, I happen to prefer Netbeans integration for maven, but that's just me :)

Some of your topics are part of deployment and release management.
You could check out a product like: Xebia DeployIt
(with an personal edition which is free)

Related

Jenkins and Maven profiles

We are working on a legacy project and the first task is to setup a DevOps for the same.
The important thing is we are very new to this area.
We are planning to use jenkins and sonarqube for the purpose initially. Let me start with the requirements.
Currently the the project is sub divided into multiple projects (not modules)
We had to follow this build structure as there are no plans for re-organising it as a single multimodule maven project
Currently the builds and dependencies are managed manually
Eg: The project is subdivided in to 5 multi-module maven projects,
say A,B,C,D and E
1. A and C are completely independent and can be easly built
2. B depends on the artifact generated by A (jar) and has multiple maven profiles (say tomcat and websphere, it is a webservice module)
3. D depends on the artifact generated by C
4. E depends on A, B and D and has multiple maven profiles (say tomcat and websphere, it is a web project)
Based on jenkins documentation to handle this scenario, we are thinking about parameterized builds using “parameterized build plugin" and "extended choice parameter plugin" with the help of these plugins we are able to parameterize the profile name. But before each build, the builder waits for the profile parameter.
So we are still searching to find an good solution to
1. keep the dependency between projects an built the whole projects if there is any change in SCM (SVN). For that we are used "Build whenever a SNAPSHOT dependency is built" and "SCM polling option". Unfortunately this option seems not working in our case (we have given an interval of 5 min for scm polling but no build is happening based on test commits)
2. Even though we are able to parameterize the profile, this seems as a manual step (is there an option to automate this part too, ie. build with tomcat profile and websphere profile should happen sequentially).
We are struggling to find a solution to cater all these core requirements. Any pointer would be greatly appreciated.
Thanks,
San
My maven knowledge is limited, however since you didnt get any response yet, ill try to give some general advice.
There are usually multiple ways to reach some aim in Jenkins, each has its pros and cons. Choosing the most fitting solution depends on the specific requirements and your environment/setup.
However you first need something that just works, then you can refine it.
A quick result you get with the following
Everything in one job
Configure your subversion repo (Multiple are possible) to be checked out into your workspace
Enable Poll SCM trigger
Build your modules/projects via Execute shell build steps. (Failed builds can be handed to the job result by using Exit 1 on a Execute shell Build step.)
However keep in mind that this will prevent advanced functionality on a per project/module basis, such as mail notifications to the dev to blame. Or trend of metrics, like warnings or static code analysis.
The following solution is easier to extend in that direction.
Wrapper job around your various build jobs
Use Build step Trigger/call builds on other projects to build A, archive needed artifacts
Use Build step Trigger/call builds on other projects with some parameter tomcatto build B tomcat version, use Copy Artifact Plugin to copy over jar from A
...
Use Build step Trigger/call builds on other projects with some parameter tomcatto build E tomcat version. Use Copy Artifact Plugin to copy all needed artifacts, you can specify parameter there if you need artifact of i.e. B tomcat version
In this setup, monitoring the svn is an issue since if you trigger it from polling SCM, it will checkout it in your wrapper workspace while you dont actually need it checked out there, but in your build jobs.
Possible solution: Share the workspace between wrapper job and your build jobs, so the duplicate checkouts in the build jobs will find the files already in the right revision. However then you *need+ to make sure the downstream jobs are executed on the same machine (there are plugins to do so)
Or even more elegant: Use a post-commit hook (See here, section Post-comit hook) on your svn to notify jenkins of changes.
Edit: For the future, its worth looking into the Pipeline Plugin and its documentation for more complex builds, this is the engine for the upcoming jenkins version 2.0, see here.
I would create 5 different jobs for ABCDE.
As you mentioned A and C would be standalone jobs so I would just do mvn clean install/pkg/verify based on your need.
For B I would first build A and then invoke another maven target in build to build B
For D, I would first build C and then build D
Finally for E , i would use invoke top level mvn targets 5 times A , B,C,D and finally E
Edit:
Jenkins 2 is out and has a built-in support for pipelines.
A few pointers for your requirements:
"built the whole projects if there is any change in SCM"
Although Poll SCM usually requires less work, the proper way to do it is to use SVN hooks.
The solution works as follows:
First you enable the Trigger builds remotely feature and enter a random token in Authentication Token.
This allows you to trigger builds remotely using Jenkins REST API (http[s]://JENKINS_URL/job/BUILD_NAME/build?token=TOKEN)
Then you create a SVN hook (a script that runs whenever you commit) which triggers the build by sending a request to that URL (using curl,wget, python,...).
There are a lot of manuals on how to create SVN hooks, here's the first result on "SVN Hooks" from Google.
"keep the dependency between projects"
I would create a different Jenkins Job for each project separately, then make sure builds are executed in the required order.
I think the best way to order your builds (dependencies) is to create a Build Pipeline using the Pipeline Plugin (previously known as Workflow Plugin).
There is a lot to explain here, so it's better you read on your own. You can start here.
There are also other (simpler) solutions, like Build Flow Plugin or Parameterized Trigger Plugin which can help create dependencies between builds, but I think Pipeline is the newest and considered a best practice (it's definitely the most advanced solution).
Still, having said that, if you feel Pipeline is an overkill for you, go for the alternatives.
I would recommend making sure each build does a mvn install to the same local repo, and also deploys the artifact to Artifactory (hopefully you have one).
Automate parameterized builds: "build with tomcat profile and websphere profile"
To do that you'll need to create parameterized builds.
That's pretty easy to do, you just check This build is parameterized in your build config and add a MVN_PROFILE string/choice parameter.
After that you can trigger each build several times, with different parameters, using any one of the plugins mentioned in the previous bullet.
Extra Tip:
While hacking your way through this, consider using Job Configuration History Plugin, it can help review and revert changes made to the configuration.
Good luck, hope this helps :)
I would consider a bit different approach to fully de-couple the projects.
If you are able to create your internal artifactory, than I would consider in the maven build each on of the dependencies as a third party library exactly like it is done with any other external libraries you are using.
This way, each such project can be seperatly built and stored in the artifactory and when a dependent project will be built it will just take the right version as mentioned in the pom file.
This way you'll have different build process for each one of the projects and only relevant projects (relevant = changed) will be built.

Including .jar files in Github for consistency

I am new to using github and have been trying to figure out this question by looking at other people's repositories, but I cannot figure it out. When people fork/clone repositories in github to their local computers to develop on the project, is it expected that the cloned project is complete (ie. it has all of the files that it needs to run properly). For example, if I were to use a third-party library in the form of a .jar file, should I include that .jar file in the repository so that my code is ready to run when someone clones it, or is it better to just make a note that you are using such-and-such third-party libraries and the user will need to download those libraries elsewhere before they begin work. I am just trying to figure at the best practices for my code commits.
Thanks!
Basically it is as Chris said.
You should use a build system that has a package manager. This way you specify which dependencies you need and it downloads them automatically. Personally I have worked with maven and ant. So, here is my experience:
Apache Maven:
First word about maven, it is not a package manager. It is a build system. It just includes a package manager, because for java folks downloading the dependencies is part of the build process.
Maven comes with a nice set of defaults. This means you just use the archtype plugin to create a project ("mvn archetype:create" on the cli). Think of an archetype as a template for your project. You can choose what ever archetype suits your needs best. In case you use some framework, there is probably an archetype for it. Otherwise the simple-project archetype will be your choice. Afterwards your code goes to src/main/java, your test cases go to src/test/java and "mvn install" will build everything. Dependencies can be added to the pom in maven's dependency format. http://search.maven.org/ is the place to look for dependencies. If you find it there, you can simply copy the xml snippet to your pom.xml (which has been created by maven's archetype system for you).
In my experience, maven is the fastest way to get a project with dependencies and test execution set up. Also I never experienced that a maven build which worked on my machine failed somewhere else (except for computers which had year-old java versions). The charm is that maven's default lifecycle (or build cycle) covers all your needs. Also there are a lot of plugins for almost everything. However, you have a big problem if you want to do something that is not covered by maven's lifecycle. However, I only ever encountered that in mixed-language projects. As soon as you need anything but java, you're screwed.
Apache Ivy:
I've only ever used it together with Apache Ant. However, Ivy is a package manager, ant provides a build system. Ivy is integrated into ant as a plugin. While maven usually works out of the box, Ant requires you to write your build file manually. This allows for greater flexibility than maven, but comes with the prize of yet another file to write and maintain. Basically Ant files are as complicated as any source code, which means you should comment and document them. Otherwise you will not be able to maintain your build process later on.
Ivy itself is as easy as maven's dependency system. You have an xml file which defines your dependencies. As for maven, you can find the appropriate xml snippets on maven central http://search.maven.org/.
As a summary, I recommend Maven in case you have a simple Java Project. Ant is for cases where you need to do something special in your build.

Recommended code-reuse

I'm starting a new project in Scala that heavily depends on source files in another Java project. At first I thought about creating a new package/module in that project, but that seemed messy. However, I don't want to duplicate the Java code in my new project. The best solution I came up with is to reference the Java project through an svn external dependancy. Another solution is creating a jar file from the original, I would attach it as a library to the new Scala project. However, this makes keeping up-to-date more inconvenient. Which route is better?
SVN external:
Easy to update
Easy to commit
Inconvenient setup
Jar file as library:
Easy to setup
Old code isn't in active development(stable, bug fixes only)
Multi-step update
Need to open old project to make changes
You have your Scala project, and it depends on parts of your Java project. To me, that sounds like the Java project should be a library, with a version number, which is simply referenced by your Scala project. Or perhaps those parts that are shared across the two projects should be separated into a library. Using build tools like Maven will keep it clear which version is being used. The Java project can then evolve separately, or if it needs to change for the sake of the Scala project, you can bring out a new version and keep using an older one in other contexts if you're afraid of breakage.
The only exception where you go beyond binary dependencies that I can think of is if the Java code itself is actually being processed in some way at compile-time that is specific to the Scala project. Like, say, annotation processing.
Using SVN externals could be a solution. Just make sure you work with branches and snapshots to make sure some update to your Java code on the trunk doesn't suddenly make your Scala project inoperable.
Whether you have mixed scala/java or not is irrelevent.
You probably want to use external dependencies (jars) if both projects are very distinct and have different release cycles.
Otherwise, you can use sbt and have your two projects be sub-projects of the same build (your sbt build file would have the scala project depend on the java project). Or even, if they are really so intertwined, just have one project with both java and scala source files. Sbt handles that just fine.
Maven is an option too.
You can very easily set up a mixed scala/Java project using maven. Have a look at the scala-maven-plugin.
https://github.com/davidB/scala-maven-plugin
Eclipse users may not be too pleased due the poor maven integration.

Maven requires manual dependency update?

I'm new to Maven, using the m2e plugin for Eclipse. I'm still wrapping my head around Maven, but it seems like whenever I need to import a new library, like java.util.List, now I have to manually go through the hassle of finding the right repository for the jar and adding it to the dependencies in the POM. This seems like a major hassle, especially since some jars can't be found in public repositories, so they have to be uploaded into the local repository.
Am I missing something about Maven in Eclipse? Is there a way to automatically update the POM when Eclipse automatically imports a new library?
I'm trying to understand how using Maven saves time/effort...
You picked a bad example. Portions of the actual Java Library that come with the Java Standard Runtime are there regardless of Maven configuration.
With that in mind, if you wanted to add something external, say Log4j, then you would need to add a project dependency on Log4j. Maven would then take the dependency information and create a "signature" to search for, first in the local cache, and then in the external repositories.
Such a signature might look like
groupId:artifactId:version
or perhaps
groupId:artifactId:version:classifier
This identifies a maven "module" which will then be downloaded and configured into your system. Once in place it adds all of the classes within the module to your configured project.
Maven principally saves time in downloading and organizing JAR files in your build. By defining a "standard" project layout and a "standard" build order, Maven eliminates a lot of the guesswork in the "why isn't my project building" sweepstakes. Also, you can use neat commands like "mvn dependency:tree" to print out a list of all the JARs your project depends on, recursively.
Warning note: If you are using the M2E plugin and Eclipse, you may also run into problems with the plugin itself. The 1.0 version (hosted at eclipse.org) was much less friendly than the previous 0.12 version (hosted at Sonatype). You can get around this to some extent by downloading and installing the "standalone" version of Maven from apache (maven.apache.org) and running Maven from the command line. This is actually much more stable than trying to run Maven inside Eclipse (in my personal experience) and may save you some pain as you try to learn about Maven.

What apps have nifty maven poms and are good as examples of maven capabilites

I'm looking for applications that have "rich" maven pom(s) and can show lot of maven capabilities(plugins). These applications are needed as showcase examples - how fast and how many this can be done with maven and appropriate set of plugins.
There are no constraint to technology or application type - it must be opensorce and easy to build. I'm not looking for best one but thouse which are worth to look and build. In yours examples please add comments, what cool features that projects's maven build offer.
Obviously, these poms will be also inspiration to improve my own/others projects poms.
I personally found that Richfaces Photo Album Example was worth to look. In this project (Java EE webapp) there are functional test with cargo and selenium, use of scm plugin (export form svn), generation and deployment of ear to jboss server.
Why not examples from maven books? The should be real projects to convince to maven boss/stakeholders/workmates.
Why I can't get first one project build by maven? Because usually projects (not all) are only built by maven, and contain no additional reports or plugins.
I find Maven's bootstrap build funny: build Maven to build Maven. Note that it is possible to build Maven with Maven already installed but I'm not sure this build shows a wide features set usage.
From this point of view, JBoss AS might already be a better example, but not the "best" (if this has a sense). Actually, I like XWiki's build (Vincent Massol is working there). Or Exo Platform's one (Arnaud Heritier is working there).
I'm pretty sure XWiki and Exo Platform are good examples as their respective build manager have a deep knowledge of Maven (as more or less active maven committers): these build are full of best practices, show the right way to do things, have a clean modules organization, etc. In other words, they are representative of the "state of the art" with Maven.

Categories