Friday, December 27, 2013

Ant,Maven and Gradle comparision

Ant, Maven and Gadle – A side by Side Comparison


A little over a year ago we were staring a new project for a client as part of a new project we had options for using a build system Ant, Maven, or Gradle were choices given that we had some time before the project started I put together a project to compare the three build systems. Up to that time the client had used Maven and neither us or the client had any particular experience using Gradle.
The project was setup so that the thee systems would build the same project and would be configured to do the same set of tasks. I picked out  a tutorialthat used the same framework that we were going to be using on the client project.  Just the first chapter of the tutorial was implemented in the project as that would be enough to gather the data needed to make an informed decision. The tasks that the build system need to do were as follows.
  • Build a deploy-able war file.
  • Run unit tests against the project.
  • Deploy the war file to a local application container
  • Clean up all the build and deployment artifacts including the expanded application folder for the deployed application.
Other items we  considered are the systems are interoperability with an IDE and its dependency management abilities.
What follows is my findings at that time.
Ant
Ant is certainly not the oldest build management system, that title probably goes to make, but it has been the standard build system for java projects since 2000 giving it ample time to mature. Ant is a configuration heavy system, you have to explicitly define all of it actions, called targets; Ant is only as intelligent as you configure it to be. Out of all the systems that were investigated this was the only one that ended up having 3 different files associated with it, the standard build.xml, build.properties, and ivy.xml (ivy will be discussed later). Being that there is not a standard way for things to be setup this particular build was the one that took the longest to setup even though most of the targets were already defined in the tutorial. It also ended up having the most lines of configuration of the bunch and the most explicitly defined targets.
  • download-ivy – download the ivy jar
  • install-ivy – install ivy into the ant class path
  • usage (default) – displays usage info (not updated)
  • build – build the java file
  • buildwar – compile a war file.
  • deploy (*) – deploy the war to the application container
  • clean (*) – clean the build artifacts and application container
  • buildtests – build the tests.
  • test (*) – runs the tests.
The targets with (*) would be main targets that would be used on a daily basis.
Dependency Management with Ivy
One of the things that Ant lacks out of the box that the other two systems have is dependency management. Apache has addressed this with a project called Ivy. Ivy uses the standard maven repositories to resolve dependencies and build class paths which are defined within an ivy.xml file. Getting the dependencies to work correctly with Ivy was the single largest time sink due to a weird configuration attribute that is not explained well in the ivy documentation. In general the ivy documentation is poor at best.
It never was figured out how to only retrieve the junit jar for tests and leave it out of the deployed war and not to include compiled tests classes. So at this point the demo still has the junit jar and tests classes being deployed with the rest of the application which should be considered a defect in that particular build file.
IDE Integration
Ant was around before eclipse and as such eclipse allows you to create a new project based on an ant target. Doing so was painless. There were a couple of hitches though, first the unit test was not imported into the project. Second is that the Ivy dependencies are not a part of that ant integration that eclipse has implemented. Apache does have an eclipse plug-in that will read that ivy.xml file and pull the dependencies into the project. Setting that plug-in up was fairly painless as it creates an ant library and you just have to make sure that it is in your class path configuration. There was one dependency that was not pulled into the project which was the application container servlet api jars which are copied from the application container home  in the build file. This was fairly simply fixed by crating a library and adding the lib directory from the application container to that library.
Maven
Maven2 has been around since 2005. It takes a different approach from ant, rather than relying on the implementer configuring everything, maven favors convention. For example if you have your source files in a folder named src/main/java maven will automatically find the sources, no configuration necessary. Everything in maven has a default setup so as long as your project follows these conventions there is no more setup needed. While Maven does state that everything can be changed to how you want it the configuration options are defied by the plug-ins which can be hard to break out of in practice. Maven does have the ability to call to ant targets so if there is missing functionality it can be added using ant and called within the maven life cycle.
The size of the maven .pom file, which is the configuration file that maven uses based on xml, ended up in the mid range of the three projects. The time to implement was the least, but this can be attributed to the current familiarity of Maven. Its dependency management is built right into the tool, and this dependency management has been so successful its the model that most other dependency management systems in the java world are based off of. Currently it is hard to find a java build systems that doesn’t use the maven repositories and is not able to use the repository to resolve any transitive dependencies. The one hitch in the dependency management was that unlike Ant I wasn’t able to use the local application container libraries. It would have been possible to install them in the local repository but that would need everyone using the project to also do this. Maven has a dependency scope which denotes that the dependency shouldn’t be included in any artifacts that are created so the build uses a library in the repository but that library is provided in the deployment environment. Using this scope another general servlet library was use for compilation but it would have been preferred to use the application container ones to avoid any possible conflicts.
Rather than targets Maven defines plug-ins and there are three main plug-ins that would be used on a daily basis. The ones that would be of use to anyone building the demo are.
  • package – build and deploy the war to the resin container.
  • clean – cleanup all build artifacts including the resin container war file copy and expanded folder.
  • test – run the test suite
IDE Integration
Eclipse doesn’t have native support for maven projects, but maven has an eclipse plug-in that generates an eclipse project which can be imported as an existing project. This works well and there were no problems doing this. The command to run this plug-in is “mvn eclipse:eclipse”. (Note: There is also an eclipse plugin called m2e which helps with maven integration into eclipse. )
Gradle
Gradle is certainly one of the newest build systems having version 1 released at the end of February 2011. Gradle rather than having a configuration based on xml like Ant and Maven is written in Groovya scripting language on the JVM. This gives us a pure programming language to develop our build on. Using Groovy Gradle can use any existing ant targets, Maven plug-ins or any Java classes making it a very powerful tool. It also uses the standard maven conventions so as long as everything is laid out like a maven project it can find everything without issue.
Dependencies are handled using the maven repositories. Groups of dependencies can be defined, Gradle plug-ins have predetermined dependency groups that you can add the dependencies to which indicate how/where the dependencies are to be used much like maven’s dependency scope. Unlike Maven you can include files on the file system easily which allowed the libraries in the application container’s lib folder to be used to compile with.
By far the number of lines to get the build to work was much less than the other two, the time to implement the build system was between ant and maven, this can be attributed to the unfamiliarity with this particular system. Of note is the unit test output is very nice and a vast improvement over the default maven surefire plug in output. Although it should also be noted that the unit tests don’t output a result on the command line, at least when all the tests pass, so that had to be added. The build tasks that are of interest for this project are
  • build – build the war file.
  • test – run the unit tests
  • localDeploy (#)- builds and deploys the war to the local resin container.
  • clean – clean the build artifacts
  • localClean (#)- clean the build artifacts and the resin container.
The tasks with (#) are ones that are explicitly defined within the build configuration, the rest are supplied by plug-ins. On average it took Gradle longer to start the build process but Gradle does seem to keep track of changes per task so if there are no changes since the last time you ran the localDeploy task Gradle will as it runs through the plug-in tree for the build tell you that there have been no changes for each task it goes through and skip running that plug-in. This sort of short cutting could save a lot of time over Maven and Ant.
IDE Integration
Much like Maven there is an eclipse plug-in available for Gradle that creates an eclipse project. The only issue was that it crated a link to a folder that it already had defined so that there was a conflict removing the link fixed the issue. Otherwise it was just as good as the Maven integration.
Side By Side Comparison
 
Ant
Maven
Gradle
Number of Files
3
1
1
Total Lines
138
73
38
approx Setup Time
6-8 hrs
1-2 hrs
3-4 hrs
IDE Integration
Eclipse Native, dependency management with plug-in
Maven Native
Gradle Native
Time to Deploy From clean (dependencies Cached)
8 seconds
13 Seconds
10.671 Seconds
Time To Clean
0 seconds
4 Seconds
2.249 Seconds
Pros-Most Mature-Quickest Build Time-Totally Configurable-Largest Current Brain Share, most experience in the company-Very quick for standard items due to conventions.-A lot of plug-ins available for different tasks-Build configuration is in Groovy for total control-Change detection will only run tasks that have changed since last run. -Smallest configuration, arguably the most readable-Has the benefit of hindsight and improves on the mistakes made by both Ant and Maven
Cons
-No native dependency management
-Longest Setup time
-Even with the long setup things still were not working as expected
-Longest build time-Can be hard to break out of a convention if needed.-Newest tech, not as much available information. -Configuration file format not as intuitive (not xml)-Biggest chance to shoot self in the foot.
Conclusions
While all are practical solutions from working with these three system I would tend to lean towards using Gradle while the format is a bit unfamiliar and the conventions used in the configuration file can be tricky to figure out first. It is hard to deny the power of being able to define custom tasks using a pure scripting language and its ability to leverage the other two build systems. This seems to result in much more compact and understandable build configurations.
Maven while being the second potential choice which is what the current Holiday Inn application uses (and in cases abuses) has the current brain trust, any project where there might be non standard things going on might have problems molding a maven driven build into what it needs to be.
We ended up in the end going with Maven, but I am planning on converting one of my side projects to use Gradle in the near future.  It should also be noted that since I wrote this maven has come out with version 3 which has several speed improvements along the lines of what Gradle does.  I was going to update the number but I can’t find the original project,  I think it would be interesting to do this again and see what difference a year makes.  But that’s for another time.

Sunday, December 22, 2013

GoF design pattern implementations examplesin Java SE and Java EE API's

You can find an overview of a lot of design patterns in Wikipedia. It also mentions which patterns are mentioned by GoF. I'll sum them up here and try to assign as much as possible pattern implementations found in both the Java SE and Java EE API's.

Creational patterns

Abstract factory (recognizeable by creational methods returning the factory itself which in turn can be used to create another abstract/interface type)

Builder (recognizeable by creational methods returning the instance itself)

Factory method (recognizeable by creational methods returning an implementation of an abstract/interface type)

Prototype (recognizeable by creational methods returning a different instance of itself with the same properties)

Singleton (recognizeable by creational methods returning the same instance (usually of itself) everytime)


Structural patterns

Adapter (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own/another abstract/interface type which decorates/overrides the given instance)

Bridge (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own abstract/interface type which delegates/uses the given instance)

  • None comes to mind yet. A fictive example would be new LinkedHashMap(LinkedHashSet, List) which returns an unmodifiable linked map which doesn't clone the items, but uses them. The java.util.Collections#newSetFromMap() and singletonXXX() methods however comes close.

Composite (recognizeable by behavioral methods taking an instance of same abstract/interface type into a tree structure)

Decorator (recognizeable by creational methods taking an instance of same abstract/interface type which adds additional behaviour)

Facade (recognizeable by behavioral methods which internally uses instances of different independent abstract/interface types)

Flyweight (recognizeable by creational methods returning a cached instance, a bit the "multiton" idea)

Proxy (recognizeable by creational methods which returns an implementation of given abstract/interface type which in turndelegates/uses a different implementation of given abstract/interface type)

The Wikipedia example is IMHO a bit poor, lazy loading has actually completely nothing to do with the proxy pattern at all.

Behavioral patterns

Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method in anotherimplementation of same abstract/interface type in a queue)

Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been encapsulated by the command implementation during its creation)

Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)

Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)

Mediator (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)

Memento (recognizeable by behavioral methods which internally changes the state of the whole instance)

Observer (or Publish/Subscribe) (recognizeable by behavioral methods which invokes a method on an instance ofanother abstract/interface type, depending on own state)

State (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)

Strategy (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been passed-in as method argument into the strategy implementation)

Template method (recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)

Visitor (recognizeable by two different abstract/interface types which has methods definied which takes each the otherabstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)