Wednesday, December 16, 2009

Making Merge, Revert and Branching Easier with SVN

In the latest release of JDeveloper (11.1.1.2.0) we've added new declarative UIs to help simplify those most crucial and complex of SVN tasks - Merging and Branching. These SVN operations can be tricky. They involve ensuring that you pick the correct location in your repository, the correct revision, and mistakes can be costly and time consuming to fix.

Take a look at the wizard below. This is available whether you choose Merge Working Copy or if you want to Merge a single file. My top tip is that you should almost always use Merge Working Copy, especially if you are working with ADF (Application Development Framework) as many of the XML metadata files for your application will have dependencies on Java files and ending up with missed or out of sync files on a merge of any sort can lead to problems.

In previous releases we simply gave you the ability to enter your URLs and revisions, almost as you would if using the command line to access SVN. But in JDeveloper we pride ourselves on providing declarative help for developers. This wizard is invoked from a checked out application context - so you are always working within your working copy.

In this first step you choose the type of merge you are undertaking, for instance Merge Selected Revision Range is used if you want to update a branch with changes from the trunk. Let's take a common scenario: User 1 is working on Branch 123_susan. She knows that primarily her work will not cause any conflict with other work on other branches or the trunk so she has not worried too much about merging the latest trunk code into her branch. However, she comes across a problem and asks User 2 to fix something in the trunk so she can progress. She is told the revision that contains the specific fix she needs so she uses Merge Selected Revision Range to get that revision into her branch. The dialog below shows the path to trunk/blues as the source and her working copy - her branch - is the destination for the merge.

The revision to be merged - 275 - was picked using the List Revisions dialog. This dialog is used whenever revisions need to be browsed or selected. Notice that selecting 275 in the top panel shows the details of that revision - the comments, the files, the action and the author
Now the user can complete move to step 3 of the wizard, choose other merge options and carry out a test merge to check her work and finally complete the merge of that one revision into her working copy. Finally, she will commit her working copy back to its branch on the repository as normal.

Once she has completed the work on her branch she will be ready to use the Re-integrate A Branch merge to get it back into the trunk of the development. As always, the way to do this is to carry out any merge into a local working copy and then commit. So the first step for the user is to do a final commit of her branch. At this stage she can remove her branched working copy as it is finished with. She checks out the latest trunk revision and now she is ready to merge her branch to her new (trunk) working copy. Let's look at that another way:

1. A branch is created from trunk
2. User 1 checks out working copy from branch and edits code
3. Commits back to branch periodically
4. User 2 commits revision 200 to trunk and User 1 merges that revision to the working copy
5. Finishes coding working copy and commits to branch
6. Checks out new working copy from trunk
7. Merges branch into working copy
8. Commits working copy back to trunk


Before Subversion 1.5 the merge of a single revision in step 4 would have caused problems when the final merge of the branch back to the trunk was done (step 7). But SVN now has merge tracking so it keeps track of the revisions that have already been merged so that the final merge of all revisions goes ahead without error.

The third merge option is Merge Two Different Trees. This allows you to compare two different branches and merge and differences back into your working copy. This is the most complicated and, I would say, the least used of the merges.

One final tip - what if you want to revert your working copy to a specific revision? Use the Merge Selected Revision Range option. In List Revisions select the range of revisions from the latest to the revision you want to revert to and click OK. This will enter the range. But the range list will be ascending - eg 258-359. To revert to revision 258 simply reverse the range order and hey presto! a revert back rather than a merge up will be done - try it out in the test merge panel to check it - and you're done!

Tuesday, December 15, 2009

Working with Versioned Database Models

What? 3 posts in 2 days? After months of silence? Isn't it amazing how time flies. Here in the JDeveloper Product Management group we've been busy all year with releases and conferences and many opportunities to get out and talk to people about the great features in our tool. But as the year draws nearer to a close and all the traveling is over I've finally got time to get out on my blog some of the things that I've been evangelizing about all year. As you'll have noticed, one of those is the great new functionality that we've introduced in database modeling.

Periodically I'm asked why we don't introduce a database repository to store database models. One that can be queried and can store versions of the modeled objects? We've been down that road (those of you who've been around for a while know what I'm talking about!) but think that what we have now in JDeveloper is much more flexible. What is it that you want from a repository? Amongst the most important answers to that question is the ability to store multiple versions of your database objects, to query and to compare them.

In previous posts I've demonstrated how you can use our Database Reporting to query your database models and output the results. In this post I want to show you how you can use JDeveloper's integrated versioning system capabilities not only to maintain multiple versions of your database model but how you can resolve any conflicts that arise when multiple users update the model, using a declarative interface.

In this example I am using Subversion (SVN), one of the versioning systems that is integrated in JDeveloper. It is an open source system, widely used in the application development world. I am not going to step through a complete process for versioning in this post, there are various tutorials, how-to, demos. white papers available on OTN and if you want more information on SVN there is a very good online book.


Here is a part of my application. Note that it contains an offline database model (Blues) and one schema (GOTTHEBLUES) containing a number of database objects. This is a project that I'm currently working on. It is stored in an SVN repository - each of the objects has a revision number next to it. Notice that the PERSONS table is at version 378. In SVN the repository revision number is advanced each time a check in of files is done. So this does not mean that the PERSONS table has been checked in 378 times, it shows that the last time PERSONS was checked in the repository moved to version 378. Likewise the last revision of PUBLICATIONS is 258, so PUBLICATIONS has not been changed since revision 258.

If I open PERSONS from the navigator - I get the declarative UI that allows me to edit that object. But that is not how the information is stored. JDeveloper stores its database models by object - in XML. Below is an extract of what you would see if you opened the underlying file PERSONS.table in a browser.


It's not impossible to read - the extract shows the detail for column LAST_NAME, a VARCHAR2 of length 25, with a comment that it was created via a DB Transform (from a class model). However, the declarative UI abstracts you from the raw XML.


But imagine if you needed to compare two versions of the PERSONS table - or you had two users who were both working on the PERSONS table and checked in their changes to the SVN repository? Comparing the raw XML files is possible, and JDeveloper does recognize XML formating, but in the latest version of JDeveloper (11.1.1.2.0) there is a new declarative UI for that too.

Imagine this scenario: two users have checked out the latest version of the application. SVN uses a copy-modify-merge versioning approach. This means that when an application is checked out a copy of that application is created on the user's local machine. SVN does not keep a record of who and where copies are checked out. It is only interested when something is commited back to the repository. So, as a user I can check out a working copy, make changes to it and if I never commit those changes back to the repository, so be it. I could do some 'what if' type coding and then decide to discard the whole copy.

In my scenario the two users have been discussing the PERSONS table and agree that the length of the LAST_NAME column is too short at 25. Unfortunately, they both decided to modify the column length in their working copy. User 1 happens to be the first to commit her changes back to the repository - so it now has LAST_NAME with a length of 50.

Now user 2 modifies her working copy, editing LAST_NAME to length 40. As good practice dictates, she Updates her working copy with the latest revision from the repository - so she can resolve any code conflicts in her working copy prior to merging her copy back in.

In this case she finds that she has a conflict between her code and the repository that JDeveloper cannot resolve automatically. She sees this in her Application Navigator. It shows the PERSON table with a conflict overlay and the differing versions of the table are also listed (see below)


But help is at hand. Double-clicking on PERSONS 379 opens the three-panel Merge window. On the left is her local version of PERSONS - with length 40, on the right is the repository version with length 50. After reviewing this she has shuffled her version into the middle Result of Merge panel. As that was the only conflict in the two files the Save and Complete Merge icon is enabled in the toolbar.
Once she saves this merge and refreshes the Application Navigator the extra conflict files will disappear and the updates will be applied to her working copy. Now she is ready to commit her working copy back to the repository so that it reflects the latest code position.

Not all changes made by multiple users cause conflicts. If the changes are complimentary - for instance one user adds a new column LOCATION and another uses changes the type of PERSONS_TYPE these changes will be added to the repository as SVN and JDeveloper recognize that there is no conflict. This is how SVN works by default, copy-modfy-merge in action. Many systems work this way, and others use the lock-modify-unlock paradigm.

If you want to review changes to a database object prior to updating your working copy, you can use one of the Compare options (Compare with Latest, with Previous, with Other Revision) before you update your working copy with the repository contents. In the example below, user 1 has used Compare with Latest to check her changes: A change to the size of FIRST_NAME and a new column COUNTRY - as shown in the right hand panel with the latest version in the repository (as shown in the left hand panel).


Finally, in this post, a short list of other tips
  • Using Compare with Other Revision don't forget to scroll to the right - and see not only revision numbers but the commit notes. Also use the filters optimize the revisions listed


  • If you make changes to a file but want to revert back to the version you checked out from the repository - use menu Versioning - Revert

  • Use the graphical Version Tree to review branches and versions of your objects


Visualizing the DB Reporting Metamodel

In my last post I gave examples of using both the pre-built reports and building custom reports on your database models.
As a P.S. to that post I want to point you to the JDeveloper Help system that comes with diagrams to help you define and understand the Database Reporting metamodel. Below is the JDEV table of contents - open at Working with Database Reports


and one small part of the Tables Report Metamodel to give you the idea. Have fun!

Monday, December 14, 2009

Using Database Reporting to Ensure Standards Compliance

In JDeveloper 11gR1 we introduced a SQL-like interface for reporting on your database models. Watch this demo to review the basic functionality. In the latest release we've added a set of pre-built reports. These reports not only get you started with reporting but also illustrate how you can use database reporting to ensure that the objects in your offline database model comply with your team's naming standards.

I say SQL-like interface because the database model you develop offline in JDeveloper is stored in XML. However, we took the decision that as most database developers are familiar with SQL it made perfect sense to provide a familiar way to interrogate the model. For instance, the pre-built report to list all tables with no Primary Key is:

SELECT
T.SCHEMA '.' T.NAME "Table"
FROM
DB_PKCONSTRAINTS C RIGHT JOIN DB_TABLES T ON C.PARENT_ID = T.ID
WHERE
C.NAME IS NULL


As you get more familiar with the meta-model you might write your own SQL queries, but there is also a declarative UI to help you traverse the model and develop the query you want.
Below is an image of the wizard, showing how the FROM clause for the above query is selected. You can also select the objects, apply different JOINs, add a WHERE, GROUP BY and aliases using the declarative UI.




Here is an example of a more complex SQL query - to report on any tables that do not have the audit column CREATION_DATE*

SELECT T.NAME FROM DB_TABLES T
WHERE NOT EXISTS
SELECT 1 FROM DB_COLUMNS C WHERE C.PARENT_ID = T.ID
AND C.NAME = 'CREATION_DATE')



Now the world is your reporting oyster - how about creating a series of reports in a Standards Project - and distributing that project to every team that is doing database development? Here is one approach:
  1. Check the Standards Project out of source control into the required application
  2. In the Standards Project open the Project Properties, in Project Source Paths select the Offline Database node
  3. Add the projects containing your database model project(s) - see image below

  4. Open each report (double-click) and select the offline database you want to run against
  5. Go to the Publish tab and enter the details of how and where you want the report to be save. In the example below I've chosen to save the report in the project that contains the database - so my audit reports can be shown to represent my offline DB Model.
  6. Use the context menu of the report format to Run the report. In my example the HTML version of the report (AuditTableCheck) is now stored in Project1 along with the database, the report format (Check_Audit_Tables) is stored in the Standards project along with the other report formats.

Let me know how you get on - it would be good to build up a list of reports written by you that could be shared with others.

*For a full example of using this in a tutorial see this Oracle By Example