Extending the BC4J Transaction
Monday 28 November 2005 @ 12:06 pm
Filed under:

One of the things we like about the Oracle Frameworks is open-ness and extensibility of the frameworks.

During our project we encountered the infamous web application problem of having two users edit the same data. The database and framework lead us to a few nice exceptions that resemble ‘RowInconsistentException’ or ‘RowAlreadyLockedException’.

The Oracle ADF Business Components framework gives us the possiblity of extending the transaction to catch this exception and do somethnig about it. We currently have decided that when these kind of exceptions are encountered that we want the transaction to be rolled back and a humanly readable exception to be displayed.

As an example we used the example of Steve Meunch (the Oracle ADF guru) and made this:


package nl.denhaag.grip.model;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import oracle.jbo.AlreadyLockedException;
import oracle.jbo.ApplicationModule;
import oracle.jbo.DeadEntityAccessException;
import oracle.jbo.DeadViewRowAccessException;
import oracle.jbo.JboException;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.RowAlreadyDeletedException;
import oracle.jbo.RowInconsistentException;
import oracle.jbo.ViewObject;
import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.TransactionEvent;

/**
* Custom ADF DBTransaction implementation.
*
* Works in tandem with a custom DatabaseTransactionFactory implementation
* which returns instances of this subclass of DBTransactionImpl2
* instead of the default one.
*
*/
public class GRIPDBTransactionImpl extends DBTransactionImpl2 {

/**
* This framework method is called by clients to commit any pending
* changes in the transaction. It will first post any outstanding changes
* then issue the database commit to end the transaction.
*/
public void commit() {
try {
super.commit();
}
catch( JboException e ) {
handleException( e ) ;
}
}

/**
* This framework method is called by clients to validate all invalid
* objects in the transaction.
*/
public void validate() {
try {
super.validate();
}
catch( JboException e ) {
handleException( e ) ;
}
}

/**
* This framework method is invoked both by the postChanges()
* and by the commit() methods to post pending transaction changes.
*
* @param te TransactionEvent object
*/
protected void postChanges(TransactionEvent te) {

try {
super.postChanges(te);
}
catch( JboException e ) {
handleException( e ) ;
}
}

/**
* This framework method is called to actually issue the final
* 'COMMIT' statement to the database to end the transaction.
*/
protected void doCommit() {
try {
super.doCommit();
}
catch( JboException e ) {
handleException( e ) ;
}
}

private void handleException( JboException e ) throws JboException {
if( e instanceof RowInconsistentException
|| e instanceof RowAlreadyDeletedException
|| e instanceof AlreadyLockedException
|| e instanceof DeadEntityAccessException
|| e instanceof DeadViewRowAccessException
) {
rollback() ;
throw new JboException( "Een andere gebruiker heeft dezelfde gegevens ook gewijzigd. Uw wijzigingen zijn niet doorgevoerd, de nieuwe gegevens worden getoond." ) ;
}
else {
throw e ;
}
}

public void rollback() {
try {
// storeCurrencies
ApplicationModule appModule = this.getRootApplicationModule();

HashMap currencies = new HashMap() ;

String[] voNames = appModule.getViewObjectNames() ;

for( int voIndex = 0; voIndex < voNames.length; voIndex++ ) {
ViewObject vo = appModule.findViewObject( voNames[ voIndex ] ) ;

Row row = vo.getCurrentRow() ;

if( row != null ) {
Key key = row.getKey() ;
currencies.put( vo, key ) ;
}
}

super.rollback();

// reset Currencies
for( Iterator i = currencies.entrySet().iterator(); i.hasNext() ; ) {
Map.Entry entry = (Map.Entry)i.next() ;

ViewObject vo = (ViewObject)entry.getKey() ;
Key key = (Key)entry.getValue() ;

Row[] rows = vo.findByKey( key, 1 ) ;

if( rows != null && rows.length == 1 ) {
vo.setCurrentRow( rows[ 0 ] ) ;
}
}
}
catch (Exception e) {
if( e instanceof JboException ) {
throw (JboException)e ;
}
else {
throw new JboException(e) ;
}
}
}
}

It actually doesn’t do much. but enough for our purposes. For the framework you need to wrap this transaction implementation in a factory:


package nl.denhaag.grip.model ;

import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.DatabaseTransactionFactory;

public class GRIPDBTransactionFactory extends DatabaseTransactionFactory {

public DBTransactionImpl2 create() {
return new GRIPDBTransactionImpl();
}
}

Even less code…

Now the magic to extend the framework: Open up your Configuration of your Application Module and goto the properties page. Scroll down all the way and find the ‘TransactionFactory’ property. Fill the with the complete classname of your own factory and presto….

Note: when using the BC tester to run your Application Module, make sure you choose the Configuration (at the top right of the screen where you select your connection) or your settigns won’t be loaded.

— By Robert Willems of Brilman   Comments (5)   PermaLink

Menu


Sha256 mining

Blog Categories

Browse by Date
November 2005
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
282930EC

Upcoming Events

Monthly Archives

Recent Comments

Links


XML Feeds Option


Get Firefox  Powered by WordPress

code validations
Valid RSS 2.0  Valid Atom 0.3
Valid W3C XHTML 1.0  Valid W3C CSS