In this article, we’re going to take a look at a development process using the technique of “Model-Driven” development. The example of this process we use utilizes the Keel meta-framework as a component toolkit and service provider, and shows how several different model projects can be used in conjunction with it.
Keel was built to provide a connector between multiple frameworks, and to provide a ready-made server side infrastructure for the development of Java applications. Although it emphasizes Web applications, Keel can be (and has been) used for desktop application development as well. This makes it a good basis for our example because we don’t restrict ourselves to any one deployment environment. Keel also features a number of services that are a “good fit” with the technique of model-driven development, making our example easier to follow.
What Is Model-Driven Development?
Like many terms, there is some debate about what Model-Driven Development entails precisely, but if we take the most generic meaning, most developers agree: Model-driven development is a style of software development that revolves around a “model,” or more precisely, a meta-data definition of the application. Often, model-driven development will entail diagrams, perhaps in UML, that in turn form the basis of the application model or meta-data. Depending on the tool being used, the development cycle then either begins with or involves code generation, whereby tools are used to prepare the initial Java code. In more advanced model-driven tools, manually edited code can even be re-generated (while losing none of the manual edits), to keep it synchronized with later changes in the model.
What distinguishes model-driven development from “regular” development is that a set of “meta-data” (the model) exists, and that the development process proceeds from this model. Exactly what the model consists of, and how it’s used, varies somewhat from tool to tool, as we will see. The goal is to make application development faster and easier, removing a lot of the tedious and repetitive work, and hopefully at the same time reducing many common errors, while also helping to ensure that the design of the application is accurately represented in the finished code.
Model-driven development is actually somewhat related to the older concept of CASE (Computer-Aided Software Engineering), but where CASE could, and often did, apply to the entire development process, model-driven development usually applies only to the translation of a design into code, and the corresponding code generation.
Today, there are a substantial number of tools for enabling model-driven development, both commercial and open-source. Some of the commercial tools go all the way from visual UML diagrams to IDE and the reverse—updating the UML based on changes to the source code. We’ll briefly examine a couple of the more popular open source tools to get a feel for the process.
Argo/UML and Poseidon
Many projects begin by using a UML diagramming tool to outline the structure of the system to be developed. One of the most popular open source tools for UML design is Argo/UML. This is a full GUI desktop application that allows creation of virtually the entire set of UML diagrams, with the ability to save those diagrams in the XMI format, which many modeling tools use as their source for code generation. A commercial extension of Argo/UML is also available, Poseidon from Gentleware (http://www.gentleware.com/), for organizations that want additional features or professional support. There is also a free community edition of Poseidon.
Once we have modeled our application in Argo or Poseidon, we move on to the actual generating tools.
The Eclipse Modeling Framework (EMF) project is a toolset that brings modeling functionality to the popular Eclipse platform and IDE. It allows a model to be created in one of several forms (including UML diagrams from a number of popular diagramming tools), and convert them into an XML representation of the application, called Ecore. This Ecore model then can be used to generate Java code with embedded XDoclet-style tags (for an introduction to XDoclet, see the XDoclet site at http://xdoclet.sourceforge.net/). The generated code then can be edited as usual. If (or, more realistically, when) the model changes, generate can be re-run without overwriting any custom code; only code identified with the special tags will be updated, allowing custom code to be created without having to “freeze” the model at any given point.
EMF’s default mechanism is to generate code for an interface pattern—that is, an interface describing the functionality being developed, and a separate implementation class that contains the specific functionality. This is a good fit with the Keel meta-framework because it (and the underlying Avalon framework) uses exactly this approach for all of its services. This makes it easy to model a new Keel service with EMF, generate the interface and skeleton implementation, and then fill in the implementation class with the actual code to render the service.
EMF is well documented (there’s an entire book about it, in fact) and highly extensible. Its API makes producing sophisticated custom generating capabilities possible, and its tight integration with the Eclipse IDE bring all elements of development together in a single tool. When used with a UML Eclipse plugin, for example (there are several available), EMF allows you to go from modeling to coding and back—all from within Eclipse.
Another choice of open source project for model-driven development is AndroMDA. AndroMDA is not integrated with an IDE, but can be used with any project that utilizes “Ant.” By default, it includes a number of “cartridges” (plugins for specific capabilities) that can generate code for both EJB and non-EJB environments from a UML model file in XMI format—just like the files that Argo/UML writes out.
To apply AndroMDA to our example, using Keel, we can immediately generate code from a UML design for JDO classes, using one of Keel’s JDO implementations. For application logic classes (called “Model” classes in Keel), we would probably want to customize one of the existing cartridges and templates (likely starting from the one that generates Struts Action classes), changing the way they produce code to comply with the Model interface.
With very little effort, then, we find ourselves with a powerful tool for turning UML diagrams directly into skeleton Keel applications, both persistence and application logic. The classes themselves contain generated XDoclet tags that produce the appropriate configuration. In practice, very little “by hand” adjustment is required to get a basic application up and running with this method.
Another option of a model-driven tool is Middlegen, which can be found at http://boss.bekk.no/boss/middlegen/. Middlegen is especially well suited for generating Java code using an existing relational database as the “model.” Given that many applications do indeed revolve around the database, this may be the right choice for some projects.
Middlegen even includes a handy utility to allow you to connect to your database (via JDBC) and view and even alter tables. Alternately, you can use plain old SQL, or the database GUI tool of your choice. Once the database is the way you want it, it is a matter of a quick “Ant” build to generate the corresponding code via one or more “plugins.”
Middlegen also, like AndroMDA, leverages XDoclet to create an associated configuration (e.g. JDO mappings). This allows us to prepare a plugin for each of the component types we want created, use Middlegen to crank out the corresponding code from the database, and then use XDoclet to automatically create the configuration files as well.
In our example of using Middlegen with Keel, we can immediately put to use the JDO plugins for Middlegen, using them to create persistent beans for Keel’s JDO implementations. With a little work, we can create a custom plugin to use Keel’s own Persistence service instead of JDO, if we prefer this. Again, Middlegen creates the actual Java classes (one per table), complete with the Keel-specific XDoclet tags for generating the configuration. Changing our database schema then becomes a simple matter of re-generating the appropriate classes—no manual coding to worry about (or to possibly introduce errors with).
Middlegen, though, is not restricted to only database beans classes; it can generate other Java code as well, such as Struts JSP pages and Actions. For use with Keel, we easily can prepare a plugin that creates a Model class to maintain each selected database table.
Middlegen uses Velocity as its internal template engine, but a developer also can write custom Java code, in the unlikely event that the required logic cannot be expressed as a Velocity template.
So, having discussed a few of the available tools, what is the development process like with model-driven development? As the name would imply, development with this technique starts with a model, whether it be a database design or a UML diagram, or even an XML Schema file. Once we’ve created the model description in the appropriate format using our design tool of choice, we go into the generation “cycle.” Depending on the tool we choose, we either initiate generation from within our IDE (in the case of EMF), or via “Ant,” as with AndroMDA and Middlegen. (Of course, many IDEs today can launch Ant from within the IDE in any case, as a convenience). Now, we review the generated files and begin the process of “filling in the blanks;” that is, providing the actual implementation code.
In the case of database beans (such as JDO or other persistence layers), we might also execute XDoclet (again, via Ant) to generate the appropriate configuration files.
If the tool we used supports it (and most now do), we then can go back and make alterations to our original model as required, and repeat the cycle: generate, code, and so forth.
Given our description of the process of Model-driven development, what are the benefits?
- Documentation: Beginning with a design model, whether it is UML or even just a database design, gives a project a head-start on documentation. UML is much more readily explained to non-technical stakeholders in a project than the corresponding code, and most database tools also can diagram a relational design in a readily understandable form.
- Accuracy: Transcribing an existing design into Java classes is much more accurately done by automation than by hand, avoiding irritating and time-consuming bugs resulting from a “mis-match” between design and code (or between code and database). Using a modeling tool can improve coding accuracy by automating this process entirely.
- Efficiency: Creating JavaBean classes that simply mirror a design already specified by a model is tedious and prone to errors. If the time consumed in creating these classes can be put to better use elsewhere, developer efficiency as a whole can be increased, and the project can move along by putting work into other parts of the process.
Model-driven development can help ensure the consistency of your development process, boost developer efficiency, and help ensure that a specification is accurately represented by the code that implements it. Given the level of tools available today, it is an easy technique to try out, and can be done entirely with open-source projects. It may be time to have a look at model-driven development for your own projects.
If you are already using Eclipse, EMF is worth careful consideration, particularly in conjunction with a UML plugin. It is a bit harder to get started with than the other tools we’ve reviewed, but the finished cohesive environment is very powerful once the effort is expended.
If your existing UML tool already is able to generate XMI, perhaps AndroMDA is the right choice because its ability to directly “digest” XMI and produce Java code can put your existing UML tool to work right away. If you are looking for an “Ant”-driven tool, AndroMDA also fills the bill.
If, like many projects, your project requires you to model directly from your database, Middlegen may be the right tool for the job because its ability to produce code directly from any JDBC datasource is unique among the tools we’ve reviewed. Mapping of persistent classes to the database is often one of the more tedious tasks in application development, even if you choose to use your modeling capabilities only in this one area of your project’s development.
About the Author
Michael Nash is the president of JGlobal Limited, a software development, consulting, training and support company specializing in open source Java technologies. He is also a core developer of the Keel meta-framework, the author of two books and a number of articles and papers about next-generation web-application development with Java, and a member of the JSR-127 (JavaServer Faces) Expert Group. He can be reached at [email protected]