Вы находитесь на странице: 1из 13

Team Development Using Subversion

An Oracle JDeveloper How To Document


Written by Susan Duncan, Oracle Corporation
May, 2008
Overview

Developing applications as a team introduces several considerations, including source and version
control for files, and utilizing shared resources. This paper details the use of integrated source control
via Subversion in JDeveloper 11g, and how your team can package and share resources. It looks at
best practices in team development, and shows how to coordinate check-in procedures and shared files
across a development team to leverage these features for maximum productivity
Even the smallest of development teams needs to maintain control of its source code. There are many
ways to do this: using a manual system, a database, a commercially available or in-house Source Code
Management (SCM) system. But whatever system you use, your system should fulfill certain basic
functions:
Integrate code changes
Maintain code history
Revert to previous code version
Compare versions and changes
Merge changes
Supported Version Control Systems
JDeveloper supports a number of version control systems. This means you can use JDeveloper as a
client to connect to the specific version control repository and manipulate your versioned code from
within JDeveloper. This gives developers greater productivity, as they dont have to open another tool or
move outside of their IDE to carry out SCM operations.
In JDeveloper 11g Subversion (SVN) support directly into the IDE. JDeveloper 11g focuses source
control support on SVN whilst continuing to enhance support for other systems, whether these are
integrated into JDeveloper (CVS) or downloadable extensions for products such as Clear Case,
Perforce etc.

Why Subversion?
SVN is a powerful, open-source version control system that has fast become the de-facto standard for
application version control. It was developed to update and overcome some of the limitations of
Concurrent Versions System (CVS), an older open-source system that was widely used before SVN was
introduced and continues to be used. There is a free online book that details not only how SVN works
but also details its improvements over CVS. It can be used to check and understand concepts and
ensure that JDeveloper's SVN support is the best it can be.
One of the major changes between CVS and SVN is SVNs usage of atomic commits. When you commit
files either all or none of the committed changes are done. If there is a problem perhaps a network

failure or conflicts between some of the changed code then you do not finish up with some of your files
committed whilst others are rejected. This was a drawback with CVS and is particularly important when
you are doing application development that has dependencies between files such as a Java file and a
corresponding XML metadata file.
Another advantage of SVN is its support for full versioning of both files and folders. A full history of them
is held on the SVN server and this allows you to add, delete, copy and rename then. CVS only versions
files and so there is not full true version history as the folders containing these files are not versioned.
In addition, replacing a file with a new one (completely unrelated) with the same name does not give a
clean history to that new file, the old history from the redundant file is maintained. In addition, if a file is
renamed in CVS then the version history of those files is lost, while Subversion copies the history to the
new element.
Where more than one developer is going to be working on the same file, there has to be a system to
prevent one developer's work unintentionally overwriting another's. The preferred solution to this with
Subversion is the copy-modify-merge model. In this model, each developer working on a file takes a
copy of it (called a Working Copy), modifies it, then merges it with the latest code in the repository. This
may sound as if it would cause frequent conflicts in the content, but in practice this is rarely the case.
When conflicts do occur, there is an efficient process for resolving them (see Resolving Code Conflicts).
As with any development project, time spent setting up your application and the SVN repository
structure for that application is time well spent.

Versioning Level
A question that comes up regularly in development teams is At what level should I version my code?
The answer should always be - at the top level. If you are using JDeveloper this means at
the Application Level. We adopt this internally for JDevelopers development and it's a top tip for best
practice.
Initial Import
If you are working on a new development you may have to carry out the initial import of your application
to the SVN repository. It makes sense to set up the repository at an early stage of development.
Perhaps once the initial application has been created. The recommended standard repository layout is
to provide an <Application Name> directory containing three folders: Trunk, Branches, Tags (see
Branching).
Using JDeveloper you can use the Subversion Navigator to add a new folder to your repository ready to
house your new application directly (see Figure 1) or you can create the folder whilst using JDevelopers
Import Wizard

Figure 1. JDeveloper's Subversion Repository Navigator


The wizard takes you through the steps to import your initial application into the repository. The easiest
way to open the wizard is to select Versioning -> Import Files from the application dropdown menu. Now
you can create the folder to hold your source code, comment your import, exclude any files or file
patterns from the initial import (see Excluding Files) and automatically checkout the code to your local
working copy ready for your development work.
Working Copy
Using JDevelopers integrated SVN Navigator and the Application Navigator it is easy to make best use
of the SVN concept Working Copy. To work on an application, you check it out from the SVN repository.
This copy becomes your working copy. In addition to the standard Commit and Update SVN commands,
JDeveloper provides additional commands Commit Working Copy and Update Working Copy. These
commands ensure that all the files in your working copy are committed/updated what
ever node in the Application Navigator you invoked the command from. Figure 2 shows the Commit
Working Copy menu being invoked from the home.jspx node in the Application Navigator.

Figure 2. Invoking Commit Working Copy From File Menu

What if my development team uses tools other than JDeveloper?


If you are using JDeveloper, you should version at the application level. This assures that your .jws
and .jpr configuration files are included in source control, especially important if you have dependencies
between projects. But what if not all your development team are using JDeveloper? Perhaps you have
some team members that use Eclipse or another IDE as well as JDeveloper? In this case it is important
to ensure that you still place both your 'jws' and your 'jpr' files under source control.
Why? Because JDeveloper looks at the state of those files to decide what versioning menu options it
makes available. For instance, say the projects making up an application had been imported into SVN
but the root level application folder and the .jws file had not been included. Perusing the versioned files
through the SVN Navigator repository you would notice that there was no .jws in the application root
folder. To overcome this you would create a new empty application and check out the JDeveloper
projects into the new application. But if you tried to access the Versioning menu at the application level
you would see 'Import Files' as the .jws file is not part of the versioned code and so JDeveloper offers

you the option to place the application under version control. If this happens the workaround is to go
back to the repository and add the .jws file to version control. This brings the IDE back into kilter and
allows you to continue using JDeveloper's integrated SVN support.

What if my development process mandates commits at the project level?


The above scenario, checking out projects into an empty application, does offer you an alternative to
versioning at the application level (best practice). By checking out individual projects you are creating a
working copy of each project as you check it out. This means that you can commit and update each
project as a separate entity. But beware, if you do this then be sure that you understand any
dependencies between the projects and are careful to update all the projects if others are also working
on them.
A better alternative is to stick to the best practice of versioning at the application level and use
JDevelopers Pending Changes windows to commit by project. Pending Changes consists of three tabs
and provides information on individual applications and projects open in your IDE that are under version
control.
The Outgoing Changes tab shows you all files that have been modified and need committing
to the repository. Figure 3 shows 1 file with an outgoing changes in the StoreFrontUI project.
The Candidates tab shows you all files that you have added to the working copy of your
versioned applications and projects (open in the IDE) since you last committed. These files need to be
added to your SVN repository using the Add command either from the Add button in the Candidates
tab or through the Application Navigator (see Excluding Files)
The Incoming Changes tab shows you all the files that have been committed to the SVN
repository by another member of the development team since you last committed your changes. (See
Comparing Versions)

Figure 3. Outgoing Changes Tab


Whether you use Update or manually review and add the changes might depend on how many and how
complex the changes are and also how easy the source is to read. Another very important consideration
is the nature of the change. In many cases, especially if you are using a framework such as Oracles
Application Development Framework (ADF) making the changes manually could be error prone as there
are dependencies between Java and their corresponding XML metadata files. For this reason best
practice is to use the Update Working Copy mechanism to update code from the repository, whether you
have used the History to manually browse changes in advance or not. It may be that you use the History
tab to find changes and the author (see Figure 6) and then communicate with the author if you are

unsure of how the changes affect your code.

What if I need to check out other code not in my application?


This might occur if your development organization has read only standard code or libraries. Rather than
each developer checking this code out and adding it to their application by hand you can use
the svn:externals property. The advantage of this is that once you set the property on your application
everyone who checks out the application from SVN will also get exactly the same set of code and
associated libraries. SVN Properties are exhaustively covered in the SVN book detailed earlier.

Figure 4. Add Subversion Property


Figure 4 shows the JDeveloper Add Subversion Property dialog. In this example the Value
String field show a value pair entered to indicate that the library adflibStoreFrontService.jar is to be
checked out of its URL in an SVN repository to a folder called external_jars. The folder external_jars will
be created in the Resource File indicated in the dialog. Invoking the dialog on this node in the
Application Navigator set this. The correct URL of the library was obtained by using the Copy URL
command on the node in the Subversion Navigator (see Figure 1)

Excluding Files From Version Control


There are a couple of ways that files are excluded from the SVN Repository. You can exclude files
during the Initial Import, ensure that certain file name patterns are never added to the repository or mark
specific files for exclusion. JDeveloper recognizes certain file types as not needing to be controlled and
additionally provides functionality for you to use the Subversion property svn:ignore.
During Initial Import
As mentioned earlier, it is possible to add filters to exclude files during the Initial Import of an application.
JDeveloper uses its Global Ignore List to provide a pre-populated list of those files/file types that you
are not likely to need versioned such as compiled Java classes (.class files). The Global Ignore List is
displayed in Step 5 of the Import wizard. You can add filters to this list. Note that these additional filters

are not added to the Global Ignore List and are not persisted between JDeveloper sessions. If you find
that there is a specific pattern that your development teams always filter then you should document this
in your development process to ensure that any team member doing an Initial Import of code is aware of
it.
Imagine this scenario: You create a new application containing some compiled Java classes. The Global
Ignore List is also used by the Application Navigator to restrict the items displayed there. Hence, you do
not see the compiled classes in the navigator but, of course, they exist on the file system. Now you
Import the application into SVN and the same filter is applied to the application. As part of the Import
wizard you choose to Check Out the imported application. Your original application location on the file
system will by default now contain your checked out application minus the excluded files. In fact, your
original files have been backed up by JDeveloper so it is possible to return to them. But from this point
on you should be working with your repository to maintain all your required code.
Excluding New Files
During application development it might be that you want to exclude certain file types or specific files
from the repository, whilst still maintaining them in your working copy. To do this you use the svn:ignore
property. There are a number of places to do this:
Candidates Tab, Pending Changes
This tab shows all the files you have not yet added to version control. You can select
files here and use the context menu to invoke the Add Subversion Property dialog. The dialog is
populated with the files you selected and you can either choose to specifically ignore those files or edit
the dialog to add file patterns.
Specific file in the Application Navigator
By invoking the Add Subversion Property dialog on a specific file you can again add
that file or a file pattern to svn:ignore.
Folder node in the Application Navigator
svn:ignore is always set on a folder so you can invoke the Add Subversion Propery
dialog from any folder node. Even when following the first two options above, the property is set on the
owning folder of the selected files

Resolving Code Conflicts


As with all development projects there are a multitude of ways to resolve code conflicts between
developers. No tool can ensure that conflicts do not occur. Much of the onus is on the development
process of the team, its methodology and, as always, communication between developers. Some
development teams where the developer who has the lock on the main code wears a lock hat to
indicate to other team members that no one else should be updating the code (doesnt work so well with
distributed teams).
JDeveloper's development process and methodology minimize conflicts but developers talk regularly to
each other and are pro-active in informing and discussing potential conflicts that might arise through
new feature development, refactoring or any of the other myriad of reasons that conflicts arise. Having
said that, SVN and JDeveloper can help to minimize these and provide strategies and answers to

resolve them
Comparing Versions
In a team environment it is inevitable that other developers change code. These changes may or may
not conflict with code that you are changing. Using the Pending Changes Incoming tab it is possible to
see what files have being changed by other developers. Figure 5 shows that another team member has
checked in a new version of home.jspx. At this stage it is not known if the changes are likely to conflict
with your working copy changes.

Figure 5. Incoming Changes Tab


Using this example, having seen that there are Incoming changes you have a number of options:
Update your code to this new version using Update or Update Working Copy.
If you choose this option then, provided there are no conflicts, your code will be
updated with these new changes. If you are not working on home.jspx then this is the obvious course of
action.
Manually check the differences between your working copy and the newer version.
To do this you can look at the History tab of your working copy of home.jspx. Figure 6
shows that there are 2 differences. In the right hand pane is your editable working copy. Choose any of
the listed versions to display in the left hand pane. In this example the latest repository version 2766
has been chosen. You can move the changes into your editable working copy from this History tab.
Select the Version History menu item from the Versioning menu to review the different versions
of the file.
This is very similar to the History tab of the file, but Version History is a read-only
compare tool. Having perused the differences, use Update Working Copy to get the changes into your
working copy. This can be used to compare the history of files that do not have editors such as the .jpr
project and .jws application files.

Figure 6. History tab of a file


Whether you use Update or manually review and add the changes might depend on how many and how
complex the changes are and also how easy the source is to read. Another very important consideration
is the nature of the change. In many cases, especially if you are using a framework such as Oracles
Application Development Framework (ADF) making the changes manually could be error prone as there
are dependencies between Java and their corresponding XML metadata files. For this reason best
practice is to use the Update Working Copy mechanism to update code from the repository, whether you
have used the History to manually browse changes in advance or not. It may be that you use the History
tab to find changes and the author (see Figure 6) and then communicate with the author if you are
unsure of how the changes affect your code.

An Alternative Approach
An alternative to the above is the lock-modify-unlock model, in which a developer locks a file, modifies it,
adds it back to the repository, then unlocks it. Locking a file does not prevent another developer from
working on a copy of the file: it prevents the content of that copy from being returned to the repository
until the lock is removed. So there is still potential for wasted effort in this model.
The lock-modify-unlock model is more suitable for working with files in binary formats, where it is
impossible to merge conflicting changes. It ensures that developers take it in strict turns to submit
changes to a file. JDeveloper provides support for the Subversion property svn:needs-lock on a file
and for retaining locks on files that you are about to commit.

Resolving Conflicts
Conflicts arise when two files have identical entries containing different content. JDevelopers Compare
and Merge tools are XML aware. This means that XML elements, properties and white spaces are read
and analysed when working to resolve avoid conflicts. If the file is not XML then if two files have identical
line positions containing different content a conflict will arise. Through its merge algorithms JDeveloper
is able to resolve very many potential conflicts but it is up to you to make final decisions on those
conflicts that are not resolveable.
If you dont use the Compare tools prior to doing a Commit of your working copy to the repository then
you will probably learn that one or more of your files has conflicts at Commit. In this case, the commit is
prohibited and, after you have Updated your working copy or specific files from the repository, any files
in conflict will have duplicate copies in the application navigator (the files represent the different versions
of the file that are in conflict. Select the Versioning -> Resolve Conflicts menu from the file version with
an exclamation point icon next to it to open the Resolve Conflicts window. Figure 7 shows an example of
this window. It consists of three panes: The left pane shows your version of the file, the right shows the
repository version and the central pane shows the resulting file once you resolve the conflicts. In this
example the right and left panes have been extended to show the content of those panes. Notice that
the file is an XML file and JDeveloper has recognized that the same element, available in both versions
of the file, contains differences. In this case, the label property differs.

Figure 7. Merge Conflict Resolution Editor

Once you have resolved all the conflicts shown in the file you can save and merge the resulting file
using the Save and Merge button at the top of the window. Now you are ready to Commit your updated
and conflict free files to the repository.

Branching
Branching is something that is seen as a requirement of a source control system although in practice it
might not be used as extensively as you might think. The mechanics of branching are simple but it is
only as good as the process that the development team uses. It requires developers to be vigilant in
what code they checkout, update and merge and to where. In Subversion a branch is a copy of code
that is maintained and versioned independently but always remembers its ancestry. Your development
process should document exactly when and how branches are to be used. It may be that a team is
asked to work on a prototype that is not wanted on the main development arm. Branching allows them
to maintain this development independently whilst also being able to update their code from the main
development as required and, at the end of the prototype, either discard their code or merge it back into
that main code line.
It may be that your branch code is a short term or a long-term project. Whatever the case, it is always
advisable to Update from the main development line often if at some stage your branch will be merged
back into the main code line.
The steps to set up and work on a branch are simple but care should be taken to understand what is
happening at each stage of the process. JDeveloper provides functionality to help with the mechanics of
following Subversions branching solution:
Create A Branch
In Subversion a branch is a copy of a code revision or a working copy taken at a point in time. Figure 8
shows the Branch/Tag dialog. You can create a branch from a Working Copy or from any revision in the
repository. In this example the HEAD Revision in the repository is to be used as a branch. The working
copy will be copied to the repository location specified in the To URL . All the history of the working copy
(held in the From location in the repository) will remain associated with the new branch.

Figure 8. Branch/Tag dialog


As well as the capability to Branch, Subversion also provides a Tag option. These two options are
identical. A Tag is generally used to give a snapshot of code at a given point in time whilst a branch is
used for independent development. To preserve the difference between a Tag and a Branch the
Subversion repository administrator tends to severely restrict the access and editing capabilities given to
any Tag directory
Working With A Branch
Once you have created a branch, whether from a working copy or from a specific revision, you are likely
to want to work on your branch code and continue to make changes and commit that code. To ensure
that your working copy commits to the correct place in the repository you use the Switch command.
Figure 9 diagrams the steps of creating and working with a branch from your working copy:
Check out, edit and commit your working copy code to the main development line
Create myBranch from your working copy and switch to myBranch (this ensures any
subsequent commit/updates to your working copy are done with the myBranch code line)
Edit and commit your working copy that is now switched to commit to myBranch
As dictated by your development process, update your branch code from the main code and
resolve any conflicts
Merge your working copy with all the changes from myBranch. Then your working copy will
reflect the merging of the latest repository code and the myBranch code. Do this by specifying the first
and last revisions from myBranch that you want to merge.
Resolve any irresolvable conflicts between main and myBranch in the normal way

At this point your working copy reflects the latest merged code from the repository and your
branch. The next step depends on where you are in your development. You might:
a. Switch your branch back to myBranch and continue working and committing changes to myBranch
b. Commit your working copy back into the main code so that all developers now have the latest
myBranch and main code available to them
c. Discard myBranch as it was a prototype and has served its purpose and is never going to be added to
the main development line

Figure 9. Typical branching scenario

Summary
JDeveloper and Subversion provide developers with an integrated team development environment. This
paper has demonstrated the client side integration and best practices for using Subversion with
JDeveloper. It is outside the scope of this paper to discuss the administration of the SVN Repository and
such issues as connection protocols.

false ,,,,,,,,,,,,,,,

Вам также может понравиться