How to avoid or circumvent the gotchas of using version control for your Oracle ADF projects.
By John Stegeman
Published December 2008
In In Part 1 of this series, you learned the basics of installing Subversion, setting up a repository, and performing basic operations using Oracle JDeveloper 11g. In Part 2, you learned how things work when you add another developer to the team. Here, in Part 3, you'll learn about some of the issues that may arise when using Subversion to version control your Oracle ADF projects.
At the time of writing, Oracle JDeveloper 11g supports Subversion version 1.4.x. Although this version works just fine with a Subversion server that is running a later version, the working copy format used by later versions of the Subversion client is not compatible with the version 1.4.x working copy format. If you install a Subversion 1.5.x client on your development machine, be sure not to perform any actions against your working copies using this version of client software; if you do so, the working copy will be silently converted to version 1.5, Oracle JDeveloper will no longer recognize it as a working copy, and you will no longer be able to use the built-in Subversion commands.
An easy way to check which version of the Subversion client you are using is to use the svn --version command:
c:\>svn --version svn, version 1.4.6 (r28521) compiled Dec 20 2007, 16:19:22
To ensure that your team works efficiently together with Oracle JDeveloper and Subversion, you should agree on a set of common standards for your ADF projects. (I provided an example in Part 2 when I wrote about code style preferences.) In addition, your team should agree on other standards such as database connection names, Oracle ADF Business Components configuration settings, and so on. If you spend some time at the start of the project agreeing on a common set of standards, you will avoid headaches later when you are forced to convert all of your code into a common style.
Subversion has a feature known as "hooks" that can help you enforce a common set of standards when checking your code into the repository. Hooks are user-supplied scripts that Subversion runs at specific times, such as before committing a change to the repository. You can easily write a pre-commit hook that uses an open-source tool such as Checkstyle to check the coding style of Java files and reject them if they do not follow the agreed-upon coding style. There is a also a framework available for Subversion called SVNChecker that has already created a Subversion hook to call Checkstyle on code before allowing it to be committed to the repository.
One common false assumption about version control systems is that having a version control system reduces the need for developer-to-developer communication. In fact, using Subversion, or any other version control system, does not reduce the need to communicate with your team members; if anything, it increases the need, because you will be using a more structured, as opposed to less structured, approach to development.
When developing applications using Oracle ADF, you should pay particular attention to coordinating development activities in the Model layer among your team members. This principle is especially important for ADF Business Components, in which a single logical object such as a View Object can comprise more than one file. If two developers both try to add or modify the same View Object, it can be very easy for the multiple files comprising the View Object to get out-of-synch and become unusable. To avoid this issue, you should confirm that your team-members communicates about the tasks they are working on.
When you develop applications using Oracle ADF, your application often depends on components that do not necessarily originate from within Oracle JDeveloper. One common example is the use of third-party libraries; another common example of external components is the database objects upon which the application depends. If you do not include these external components in your version tracking approach, you may have problems when part of your team uses a different version of the external components than the rest of your team. To avoid this problem, you should include the external components in your version tracking approach.
Now, let's address some if the more common external components involved.
Although Apache Maven has a method for tying project dependencies to a specific version of a third-party library, Oracle JDeveloper 11g (as of this writing) does not have built-in support for Maven. Also, not everyone uses Maven in their projects; so, I'll describe an alternative approach.
For demonstration purposes, let's assume that you want to use the Apache POI libraries in your example application. One way to do this would be download the required JAR files to some location on each developer's file system and create a library definition in Oracle JDeveloper to point to the JAR files. However, when using this approach, it will be possible for different developers to have different versions of the JAR files, and thus cause problems. To avoid these types of issues, an approach that I use is to create an Oracle JDeveloper project to contain all of the third-party JAR files; this project can then be added to the Subversion repository and controlled in the same manner as your application's source code.
To demonstrate, let's see how team member John uses this approach with the Apache POI libraries. The first thing John does is to download the appropriate files from the Apache POI Web site. Then, he creates a directory within his application's directory structure to hold third-party libraries:
Figure 1 Creating a Directory for third-party Libraries
Next, John creates a subdirectory to hold the POI JAR files and extracts them from the POI distribution into the directory:
Figure 2 Extracting the POI JAR files
In Oracle JDeveloper, John creates a new project to hold the third-party JAR files. He creates the project in the directory he created earlier. He does this using the shortcut menu in the Application Navigator:
Figure 3 Creating a New Project for third-party libraries
When prompted, he selects Generic Project as the project type:
Figure 4 Selecting Generic Project
John then specifies an appropriate project name and provides the directory he created earlier. There is no need to add any libraries to this project:
Figure 5 Specifying the Project Name and Directory
The project is now visible in the Application Navigator, although there are no files visible when expanding it:
Figure 6 Newly created projectIn order for the POI JAR files to be a part of the project, John must configure the project to include all subdirectories in the source path for the project's resources. To do that, John right-clicks the 3pLibs project and chooses Project Properties:
Figure 7 Displaying the project's propertiesThen, by expanding the Project Source Paths node and selecting Resources, he can click the Include Content from Subfolders checkbox to include JAR files from all of the project's subdirectories:
Figure 8 Including subdirectories in the project's resourcesAfter doing that configuration, the POI JAR files are now visible in the Application Navigator:
Figure 9 POI JAR files in the Application NavigatorFinally, John uses the Pending Changes window to add the four new files (the new Project file and the three JAR files) to the Subversion repository and commits the changes with an appropriate comment:
Figure 10 Committing new project and JAR filesJohn can now create a new library definition that includes the POI JAR files and start using Apache POI in the project. The next time Josephine updates her working copy, she will also see the new 3pLibs project and the Apache POI files. In the future, if the team decides to update the version of Apache POI used, they can download the new version, replace the existing JAR files with the updated ones, and commit the changes to the repository, ensuring that the entire team is using the same version.
Another common example of external dependencies is the database objects (tables, stored procedures, etc) against which you build your application. If you use the approach, as many development teams do—where each team member has his/her own development database—it's possible for your team members' databases to get out-of-synch, leading to versioning issues. In order to help prevent these types of issues, you should store in your Subversion repository any artifacts you need to keep your database objects up-to-date.
In Oracle JDeveloper, there are several ways you can do this, including:
In many Oracle ADF-based applications, some components are modified whenever adding new components to the application. I call these components "chokepoints." Two common chokepoints in an application developed using Oracle ADF are Application Modules in the Model layer and the faces-config.xml file in the View layer. If your team does not take care when modifying these components, it is easy for two team members to modify the file at the same general time. In many cases, Subversion will not be able to merge the changes, or the result of a merge is an unusable component (because merging works on textual and not semantic differences).
To avoid such chokepoints, I use one of two methods, depending on team size and the stage of development.
The first method is to assign one developer to own changes to each chokepoint component; when another developer needs to change the component, he/she communicates the required change to the component owner, who then makes the change and commits it to the repository. The benefit of this method is that it practically eliminates the possibility of conflicts and semantically incorrect merging. The primary downsides are that this method requires that developers adhere to manual procedures and that it requires an additional layer of communication, possibly adding bottlenecks to the development process. In practice, I have found this method to be more useful in the early stages of development, when the chokepoint components are undergoing more frequent changes.
The second method is to allow any developer to make changes to the chokepoint components. If a conflict occurs when committing or a merge occurs when updating, the developer who experiences the conflict/merge then reverts the component back to the latest version of the component from the repository (in the process, reverting any changes he/she made to the object) and re-applies/re-codes his/her changes to the component. This method avoids the possibility of having a Subversion merge operation create an unusable object at the expense of requiring developers to do more work in the case of a merge/conflict. In practice, I have found this method to be more useful in the later stages of development, when the chokepoint components are undergoing less frequent changes, and thus the probability of conflict/merge is lower.
You have now seen how to use Oracle JDeveloper 11g with a Subversion repository to work in a team environment with multiple developers and multiple branches of development and are aware of the common potential issues. You should be ready and confident to use Subversion in any Oracle ADF project, whether it involves a single developer or a team of many developers.
John Stegeman ( http://stegemanoracle.wordpress.com) is an Oracle ACE Director (Oracle Fusion Middleware) and the principal architect in the EMEA region for Cambridge Solutions, a global BPO and IT services firm. He has been working with Oracle products since 1990 and with Oracle JDeveloper since Version 3.