We are currently very busy with a major rewrite of the JHeadstart Developer's Guide for the upcoming JHeadstart 10.1.3.2 release. Not only will we document the numerous new features, we also take the opportunity to add chapters and sections that discuss many frequently asked questions over on the JHeadstart Discussion Forum. One such popular topic is team-based development. A whole new chapter will be devoted to this topic, including a section on version control. Since the content of that section includes useful information for versioning ADF applications in general, and is independent of ADF and JHeadstart versions, we will share a preview of it with you through this blog post.
The following topics are discussed:
- Version control models
- Requirements for a good version control system
- Which files to version?
Version Control Models
When selecting a version control system, you have to
choose between two basic models of version control: file locking and version merging.
Wikipedia provides the following definitions for these two models
- File Locking: The simplest method of preventing concurrent
access problems is to lock files so that only one developer at a time has write
access to the central "repository" copies of those files. Once one
developer "checks out" a file, others can read that file, but no one
else is allowed to change that file until that developer "checks in"
the updated version (or cancels the checkout).
File
locking has merits and drawbacks. It can provide some protection against
difficult merge conflicts when a user is making radical changes to many
sections of a large file (or group of files). But if the files are left
exclusively locked for too long, other developers can be tempted to simply
bypass the revision control software and change the files locally anyway. That
can lead to more serious problems.
- Version Merging: Most version control systems,
such as CVS and SubVersion, allow multiple developers to be editing the same file
at the same time. The first developer to "check in" changes to the
central repository always succeeds. The system provides facilities to merge
changes into the central repository, so the improvements from the first
developer are preserved when the other programmers check in.
The
concept of a reserved edit can provide an optional means to explicitly
lock a file for exclusive write access, even though a merging capability
exists.
For developing applications using JDeveloper, ADF and JHeadstart,
we recommend to use the version merging model, for the following reasons:
- It is a file-oriented development environment. Even for
small to medium-sized applications, you will easily have hundreds of files to
manage. It is inevitable that at some point multiple developers need to modify
the same files. Using the file locking
model this means that developers will have to wait for each other to finish
a task and check in again. Although the number of �locking conflicts� can be
reduced by a smart distribution of development tasks, it is our experience that
you can never entirely avoid it.
- The files that most often are modified simultaneously
by multiple developers are XML files, which by its structured nature are very
well suited for automatic merging by version control systems. It is our
experience that a version control system like SubVersion is also very good at
merging Java files, the other most used type of file in this development environment.
- When generating your application using JHeadstart, many
files are modified during a generation run. When using the file locking approach,
you need to know upfront which files will be modified by the JHeadstart
Application Generator: all these files need to be checked out prior to
generation, otherwise they remain read only and will not be modified by JHeadstart.
It requires in depth knowledge of JHeadstart and ADF to be able to correctly �predict�
which files will be modified in a specific generation run. With the version merging approach this is not
an issue, once you have finished a development task, the version control system
will tell you which files have been modified and need to be committed to the
version control repository.
Requirements for Good Version Control
When selecting a version control system, make sure the
system provides functionality to address the following requirements:
- It supports the Version Merging model (see
previous section).
- It provides a so-called Atomic Commit. With this we mean that when you have modified
a number of files that you want to commit to the version control repository,
you want either the entire transaction to be committed, or the entire
transaction to be rolled backed when a version conflict is detected which
cannot be solved by an automatic merge. In other words, either all files are
committed succesfully, or none of the files are committed. A version control
system like CVS does not support an atomic commit. This means that some files might
be committed to the repository, and then a version conflict is detected and the
rest of the files cannot be committed. When this happens, you end up with an
inconsistent situation in your version control repository since there are many
interdependencies between files in an ADF environment. Obviously, when other
developers update their local copies with this inconsistent set of files, they are
likely to run into all sorts of problems and error messages.
- It detects file changes by comparing file content
rather than the timestamp of the file. This requirement is particularly
important when using JHeadstart: when you regenerate your application using the
JHeadstart Application Generator, the content of many files might remain the
same, although the file is recreated with a new timestamp. When you commit your work after you completed
a development task, you do not want a new version of all these unmodified files
to be committed to the repository. Otherwise, it will be really hard to find back
versions that contained a real change, being
a version you might want to revert to when you want to undo some work.
- An efficient and easy to use user interface to perform
common versioning tasks. Developers should spend as little time as possible
with version control tasks. An intuitive user interface for common tasks like
updating their local copy, committing changes, reverting to previous versions,
resolving merge conflicts, and creating application releases is essential to
meet this requirement. Ideally, the versioning user interface is integrated
with JDeveloper, although in our experience it is not a big deal to switch with
Alt-Tab to a stand-alone GUI for versioning when JDeveloper integration is not
available, or less feature-rich.
A popular open source version control system that meets
all of the above requirements is
SubVersion (also known as SVN) . SubVersion
has been built by the same community that is responsible for CVS. It is
intended as a replacement for CVS, keeping all the good things of CVS, and fixing
the bad things (like the absence of an atomic commit).
TortoiseSVN is an excellent stand-alone SubVersion GUI for
the Windows platform, nicely integrated with MS Windows Explorer. JDeveloper integration is also available.
The JHeadstart team has successfully used SubVersion and
TortoiseSVN on a number of projects, see also the JHeadstart blog post "Managing Your Project Files: Using Subversion". This does not imply you should make the
same choice. Version control is no rocket science, any system that meets the
above requirements will do the job.
Which Files to Version?
We recommend to version all files in your project, except
for
- derived files like all compiled Java classes and XML and
property files that are copied to the classpath. In SubVersion, the easiest way
to exclude these files is by adding the root directory of the classpath
(typically the /classes directory) to
the ignore list. This can be done by a right-mouse-click on the folder, and then
choose Tortoise SVN -> Add to Ignore List �
- files in the temporary directory created by ADF Faces. When
running your application in JDeveloper, a /temp directory is created under
the WEB-INF directory, which holds cached ADF Faces files like images and
stylesheets. This directory is not required to run your application and does
not need to be versioned.
- the files created by JDeveloper in the root:
appname-data-sources.xml, appname-jazn-data.xml, appname-oc4j-app.log,
appname-oc4j-app.xml and application.log. If you are using JAAS-JAZN authorization,
you do might want to version appname-jazn-data.xml since it holds the users and
roles you have defined in JDeveloper for the project.
- the faces-config diagram files, with extension �.oxd_faces�.
When generating your application with JHeadstart, the faces-config diagram
typically looks rather messy, so unless you spend some time in cleaning up the
diagram, it doesn�t make a lot of sense to version these files. They are
usually created in a separate folder (/model by default), so you can exclude the
whole folder from versioning.
Hint: when using TortoiseSVN, the �Add to Ignore List�
option in Windows Explorer is only available on unversioned folders directly
below a versioned folder.
When committing
a project for the first time, it is easier to exclude folders using the right-mouse-click
popup menu in the Commit dialog.