More than ten years ago, Joel Spolsky of "Joel on Software" fame wrote The Joel Test: 12 Steps to Better Code. It was a great set of 12 yes/no questions, all of which you should be able to honestly answer "yes" if your team is to have any hope of producing good software in a timely and efficient manner.
The Joel Test stands up pretty well even today. Joel's first two questions, "Do you use source control?" and "Can you make a build in one step?" are a good start at addressing the need for build automation. With the tools available today, however, I suggest that build management (not just automation) and release management should be added to the "must have" list for productive software development teams.
Since I mostly work in Java, I'll talk about Java build and release management. There are a few comprehensive tools for Java build and release management (actually many more build management tools than release management tools), but the most popular by far is Apache Maven.
Maven started in 2001 as a part of the Apache Alexandria project, moved to be a part of the Apache Turbine project in 2002, became a top-level Apache project in 2003, and had its first milestone release, v1.0, in October of 2005. Version 2.2.1 has been in wide use since its release in August of 2009. Version 3.0 was released in October of 2010, and the current version, 3.0.1 was released in November 2010.
Maven bills itself as a "software project management and comprehension tool". Its most basic use is as a build tool, commonly as a replacement for Apache Ant, but it does several other things, which taken together, really do form a useful software project management and comprehension tool. Maven is certainly not an absolute requirement for a good software development team, but the issues that it addresses must be addressed somehow. If your Java development team is not currently addressing these issues in a satisfactory way now, Maven is a good way to get started addressing them in a coherent way.
As a build tool, Maven takes the now-common "convention over configuration" approach that seems to have started around 2004 with the Ruby on Rails web framework. As such, Maven was designed to be a highly opinionated tool, giving structure to the free-for-all that Ant usage had become in many projects. Maven is based on the Project Object Model, an XML configuration file that specifies what goes into a project, but unlike Ant, generally not how to build it. This is where the convention over configuration comes in - you put your source code and other build artifacts in a directory structure that Maven expects, and then Maven can build it with no further configuration. This results in both simplified build management (no build script to write and maintain), and a project that anyone familiar with Maven can build. There is a well-defined build lifecycle, with well-defined targets: "mvn install" builds, tests, and packages any project built with Maven, and installs the resulting artifact in a local repository (more about repositories later). This is a great improvement over Ant, where the names of the build targets, and what they do are up to the whim of the person writing the Ant build script.
Maven is much more than just a build tool. It has many more features, but to me, the most important are Dependency Management and Release Management.
Dependency Management is all about dealing with the libraries (jar files) upon which your project depends (direct dependencies), and those jar files' dependencies (transitive dependencies). With Ant or any other build system that does not manage dependencies, this is left as a manual exercise for the developers. Typically, all of the dependencies are resolved manually, and all of the jar files are put into the project's 'lib' directory. This frequently means that multiple projects using the same third-party libraries will each need to keep a copy of them.
Maven's paradigm is to have the developer declare the project's direct dependencies in the POM. Maven then resolves the transitive dependencies, and pulls the required jar files (direct and transitive dependencies) from a Maven Repository at build time. Jar files are not kept within the project, just the specification of which jar files to use at build time. There is a "standard" external repository (the "central" repository) that is web-based, and hosted by maven.org, and a local repository in the filesystem on the developer's machine. Jar files are pulled from the central repository, or other external repositories that may be configured, and cached in the local repository.
This arrangement works well for small, one-off development efforts, but many shops have reusable jar files of their own that are used by multiple internal projects. Historically, many development teams have distributed these reusable in-house developed jar files by either putting them on a shared network directory, or by checking them into the source code version control system. This results in a process that is more manual and cumbersome than it should be, and generally violates the DRY principle.
Using Maven instead of Ant or a home-grown build system, and managing dependencies through it are a good first step, but for reusable code, Release Management becomes important, and again, Maven can help. Maven, through its release plugin, supports a well-defined release lifecycle, and allows teams to store their reusable code in a centralized Maven repository, just like the "standard" jar files that are kept in the central repository. Teams (or whole companies) can set up their own internal, web-based repository that either enhances or replaces the central repository. Using Maven, they can then "release" their jar files to this repository. Projects using Maven can then declare these jar files as dependencies the same way that they do for jar files in the central repository, and they will be resolved by Maven. No need for shared directories, or placing binaries in the source code version control system. The release plugin takes care of incrementing version numbers and updating them in the version control system, in a standard way.
The features that have been presented here are just the most prominent ones - Maven is capable of much more, especially with its extensive list of plugins. If your team is not using Maven (or something like it), or is only using Maven as a build tool, I encourage you to spend some time learning more about Maven. It will be time well spent. There are the Maven project's own "Getting Started" guides and a series of books by Sonatype (the commercial company behind Maven) for starters.
Sonatype provides online, instructor-led training courses, and here at Chariot Solutions, we offer public, on-site training in our Ft. Washington, PA facility, as well as custom private courses.
Friday, December 31, 2010
Tuesday, December 28, 2010
Painless Java Desktop Application Development with Griffon, MigLayout, and IntelliJ
As Java consultants and developers, a very large percentage our projects are web applications.
We have become accustomed to depending on MVC web frameworks, and almost take for granted that at some level, we will be handling HTTPServletRequests, providing HTTPServletResponses, and deploying our applications to either a servlet container or a full J2EE server.
Every once in a while, however, the need arises to write an old-fashioned, desktop, thick-ui, non-web-centric application. If you have ever written a Java Swing application, you may have painful memories of dealing with things like BorderLayouts, GridBags, Event Listeners and Event Dispatching Threads, JFrames, and the like.
As a web developer, when you think about building your desktop application, you might start to think about how you will structure your application, and how you will build and package it. Will you have to re-package your code and all of your dependencies in one giant uber-jar?
Will you make it a web-start application? Fortunately, some folks have been thinking about, and working on these issues.
Griffon is a Groovy-based MVC framework for writing desktop applications. It is written by the Groovy Swing team, and is heavily influenced by Grails. If you have worked with Grails, then Griffon will be a very familiar environment. Griffon answers all of the above questions, and more.
Using the convention-over-configuration and command-line-driven scaffolding paradigms made popular by Ruby on Rails, Django, and Groovy on Grails, among others, Griffon generates the project structure, the model, view, and controller objects, and all of the configuration for you. You then customize these to produce your application.
Working in Groovy, of course, makes this a much more pleasurable experience, dispensing with the ceremony of Java development, and letting you write high-level, fairly terse, yet expressive code, and enabling you to accomplish quite a bit very quickly. The prime example of this in the Griffon framework is the SwingBuilder object - a Groovy Builder that provides a DSL for building Swing user interfaces. Views in Griffon are SwingBuilder scripts, and greatly simplify the task of creating Swing UIs.
Griffon uses the Gant build system (as does Grails), and by default, packages your application with all its dependencies as an uber-jar (with the correct manifest entries to make it 'executable'), as an applet, and as a java-webstart application.
When working with Swing, even with the SwingBuilder, one potentially still has to deal with the frustration of laying out the user interface by using a LayoutManager. GridBagLayout is flexible (too flexible?), but about as complicated as it can get. BorderLayout is fairly simple, but the simplicity comes at a cost - you typically wind up nesting lots of BorderLayouts in other BorderLayouts to get the desired behavior. Over the years, alternate layout managers have appeared, and some are quite useful, most notably the JGoodies Form Layout and RiverLayout. I tried MigLayout with my Griffon project, and found it to be very flexible and easy to use.
Here is a screenshot of the main UI of my application:
As mentioned previously, the View is a Groovy SwingBuilder script. The first part of the script sets up an 'application' - the application's "MainFrame", which Griffon interprets according to the runtime environment - for a stand-alone application, it will build a JFrame, and for an applet it will build a JApplet:
Next is setup of the actions and the menu bar that uses the actions, in this case, a simple 'File' menu with a 'Quit' menu item to exit the application.
Note the use of Groovy closures for associating the Action object with implementation of the action.
I chose to use the MigLayout for the main panel of the view. There are lots of ways to initialize a MigLayout, I used the "fill" parameter to the constructor, which tells it to grow to occupy all available space, which makes sense here because it is the top-level component in the frame.
As you can see in the screenshot, there are three groupings of controls - the group of fields above the separator (the input fields), the group of fields below the separator (the output fields), and the "button bar" at the bottom (only one button). To achieve these groupings, I added two panels, each with MigLayout initialized with "fill", as with the main frame, and a third panel with a FlowLayout for the button bar.
These MigLayouts are given constraints of "growy" and "wrap":
With this configuration, the MigLayout in the main frame gives the button bar it's preferred size, and resizes the other two panels as the main window is resized, giving equal weight to them.
The two MigLayout panels are very similar. Each has sets of label / input field pairs, which look like:
One big "gotcha" here is that bi-directional binding is not supported. It is possible to bind in each direction, but not both directions at the same time. As one might expect, lots of people are asking for this capability, so I wouldn't be surprised to see it show up soon. I ran into this when trying to set the initial value of the field from the value in the model. The answer for this case is to use the "value" property as shown above - it gives the field it's initial value, and does not participate in the binding mechanism, so it doesn't present the same problem as bi-directional binding. If you do truly need bi-directional binding, at the moment, you'll have to roll your own.
Here is the full source code for this View.
Due to its highly-developed sense of structure and general lack of need for configuration, working on a Griffon application using the command line and a text editor is very straightforward. However, IDE support is always nice. Eclipse does not directly support Griffon, but does support Groovy. Both NetBeans and IntelliJ have direct support for Griffon projects. IntelliJ 9 and 10 have direct support for creating, importing, testing, running, and debugging Griffon applications, and I found these features to work quite well.
I found the combination of Groovy, Griffon, MigLayout, and IntelliJ to be an extremely productive environment for creating Swing applications, providing much of the application infrastructure, allowing me to dispense with ceremony and concentrate on writing the parts of the application that make it unique. Before embarking on a large or mission-critical Griffon project, however, you do need to be aware that Griffon is still in Beta (0.9.2-beta-3 was just released on Dec. 21st, 2010), and so is still in a bit of a state of flux.
If you are interested in reading about Griffon, there's documenatation at at the Griffon home page, and the Griffon In Action book is available from Manning.
We have become accustomed to depending on MVC web frameworks, and almost take for granted that at some level, we will be handling HTTPServletRequests, providing HTTPServletResponses, and deploying our applications to either a servlet container or a full J2EE server.
Every once in a while, however, the need arises to write an old-fashioned, desktop, thick-ui, non-web-centric application. If you have ever written a Java Swing application, you may have painful memories of dealing with things like BorderLayouts, GridBags, Event Listeners and Event Dispatching Threads, JFrames, and the like.
As a web developer, when you think about building your desktop application, you might start to think about how you will structure your application, and how you will build and package it. Will you have to re-package your code and all of your dependencies in one giant uber-jar?
Will you make it a web-start application? Fortunately, some folks have been thinking about, and working on these issues.
Griffon is a Groovy-based MVC framework for writing desktop applications. It is written by the Groovy Swing team, and is heavily influenced by Grails. If you have worked with Grails, then Griffon will be a very familiar environment. Griffon answers all of the above questions, and more.
Using the convention-over-configuration and command-line-driven scaffolding paradigms made popular by Ruby on Rails, Django, and Groovy on Grails, among others, Griffon generates the project structure, the model, view, and controller objects, and all of the configuration for you. You then customize these to produce your application.
Working in Groovy, of course, makes this a much more pleasurable experience, dispensing with the ceremony of Java development, and letting you write high-level, fairly terse, yet expressive code, and enabling you to accomplish quite a bit very quickly. The prime example of this in the Griffon framework is the SwingBuilder object - a Groovy Builder that provides a DSL for building Swing user interfaces. Views in Griffon are SwingBuilder scripts, and greatly simplify the task of creating Swing UIs.
Griffon uses the Gant build system (as does Grails), and by default, packages your application with all its dependencies as an uber-jar (with the correct manifest entries to make it 'executable'), as an applet, and as a java-webstart application.
When working with Swing, even with the SwingBuilder, one potentially still has to deal with the frustration of laying out the user interface by using a LayoutManager. GridBagLayout is flexible (too flexible?), but about as complicated as it can get. BorderLayout is fairly simple, but the simplicity comes at a cost - you typically wind up nesting lots of BorderLayouts in other BorderLayouts to get the desired behavior. Over the years, alternate layout managers have appeared, and some are quite useful, most notably the JGoodies Form Layout and RiverLayout. I tried MigLayout with my Griffon project, and found it to be very flexible and easy to use.
Here is a screenshot of the main UI of my application:
As mentioned previously, the View is a Groovy SwingBuilder script. The first part of the script sets up an 'application' - the application's "MainFrame", which Griffon interprets according to the runtime environment - for a stand-alone application, it will build a JFrame, and for an applet it will build a JApplet:
package servicetester
import java.awt.FlowLayout
import net.miginfocom.swing.MigLayout
application(title: 'Service Tester', minimumSize: [297, 200], maximumSize: [297,200], location: [50, 50], pack: true, locationByPlatform: true) {
Note that minimumSize, maximumSize, location, etc. are set as properties here. In straight Java Swing code, these would have been at least one line of code each, and several would have involved building Dimension objects.Next is setup of the actions and the menu bar that uses the actions, in this case, a simple 'File' menu with a 'Quit' menu item to exit the application.
Note the use of Groovy closures for associating the Action object with implementation of the action.
actions {
action(id: 'exitAction',
name: 'Quit',
closure: { System.exit(1) },
mnemonic: 'Q',
accelerator: shortcut('Q'),
shortDescription: 'Quit'
)
}
menuBar(id: 'menuBar') {
menu(text: 'File', mnemonic: 'F') {
menuItem(exitAction)
}
}
I chose to use the MigLayout for the main panel of the view. There are lots of ways to initialize a MigLayout, I used the "fill" parameter to the constructor, which tells it to grow to occupy all available space, which makes sense here because it is the top-level component in the frame.
panel(border: emptyBorder(12), layout: new MigLayout('fill')) {
As you can see in the screenshot, there are three groupings of controls - the group of fields above the separator (the input fields), the group of fields below the separator (the output fields), and the "button bar" at the bottom (only one button). To achieve these groupings, I added two panels, each with MigLayout initialized with "fill", as with the main frame, and a third panel with a FlowLayout for the button bar.
These MigLayouts are given constraints of "growy" and "wrap":
panel(layout: new MigLayout('fill'),
constraints: "growy, wrap") {
"growy" means "grow vertically", and "wrap" means that the next component should be placed below, instead of to the right.With this configuration, the MigLayout in the main frame gives the button bar it's preferred size, and resizes the other two panels as the main window is resized, giving equal weight to them.
The two MigLayout panels are very similar. Each has sets of label / input field pairs, which look like:
label(text: 'AMQ Broker URL:')
textField(
id: 'brokerUrl',
columns: 40,
text: bind(target: model, targetProperty: 'brokerUrl', value: model.brokerUrl),
enabled: bind {model.enabled},
constraints: 'wrap'
)
The "text:bind" property binds the value entered in the textField to a property in the model - the value entered by the user is placed into the model.One big "gotcha" here is that bi-directional binding is not supported. It is possible to bind in each direction, but not both directions at the same time. As one might expect, lots of people are asking for this capability, so I wouldn't be surprised to see it show up soon. I ran into this when trying to set the initial value of the field from the value in the model. The answer for this case is to use the "value" property as shown above - it gives the field it's initial value, and does not participate in the binding mechanism, so it doesn't present the same problem as bi-directional binding. If you do truly need bi-directional binding, at the moment, you'll have to roll your own.
Here is the full source code for this View.
Due to its highly-developed sense of structure and general lack of need for configuration, working on a Griffon application using the command line and a text editor is very straightforward. However, IDE support is always nice. Eclipse does not directly support Griffon, but does support Groovy. Both NetBeans and IntelliJ have direct support for Griffon projects. IntelliJ 9 and 10 have direct support for creating, importing, testing, running, and debugging Griffon applications, and I found these features to work quite well.
I found the combination of Groovy, Griffon, MigLayout, and IntelliJ to be an extremely productive environment for creating Swing applications, providing much of the application infrastructure, allowing me to dispense with ceremony and concentrate on writing the parts of the application that make it unique. Before embarking on a large or mission-critical Griffon project, however, you do need to be aware that Griffon is still in Beta (0.9.2-beta-3 was just released on Dec. 21st, 2010), and so is still in a bit of a state of flux.
If you are interested in reading about Griffon, there's documenatation at at the Griffon home page, and the Griffon In Action book is available from Manning.
Subscribe to:
Posts (Atom)


