2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2020

09/07/2005: Using a CustomEditorConfigurer to Specify a Lucene FSDirectory Using Spring

When I started to use Spring with my Lucene application, I searched for an easy way to specify the directory name where the Lucene repository is stored. Since the FSDirectory class is not instantiated directly (you need to call FSDirectory.getDirectory), I couldn't see how to configure Spring to create the object for me.

Then I discovered that the JavaBeans api has the ability to automatically convert from a String to any other class using a configurator object. With this ability, specifying a bean that uses an FSDirectory can be done in the following way:

<bean id="serverDatabase" class="com.server.DB" method="setup">
  <property name='directory'><value>data/LuceneRepsitory</value></property>
</bean>

The idea is that when Spring wired beans together some configurer object would convert that String into a Lucune FSDirectory object. This conversion is done by the following Java class:

public class FileSystemLuceneDirectoryEditor extends PropertyEditorSupport {
    public void setAsText(final String textValue) {
        try {
            final boolean fileExists = new File(textValue).exists();
            final boolean createDirectory = fileExists == true ? false : true;
            setValue(FSDirectory.getDirectory(textValue, createDirectory));
        } catch (IOException e) {
            throw new CriteriaWatchException(e);
        }
    }
}

The configurer class needs to be introduced to Spring through its XML configuration file:

  <bean id='customEditorConfigurer' class='org.springframework.beans.factory.config.CustomEditorConfigurer'>
    <property name='customEditors'>
      <map>
        <entry key='org.apache.lucene.store.Directory'>
          <bean id='luceneDirectoryEditor' class='FileSystemLuceneDirectoryEditor'/>
        </entry>
      </map>
    </property>
  </bean>

After the above work is done, Spring automatically converts any String values that are destined to be Directory parameters.

05/05/2005: Transaction Management Using Sonic XIS Server, Oracle, and Spring

The WorldSync application has three types of transactions that need to be managed:

  • XIS
  • Direct use of Oracle
  • Spring-mediated use of Oracle

Let's look at each transaction type to see how the API is used.

XIS (with synchronized Oracle transactions)

When working with the XIS engine, you should only deal with the org.wwre.xis.transaction.TransactionHelper class. Oracle connections are managed automatically to coincide with XIS actions.

TransactionHelper.getClientSession()
getLocalReadOnlySession()
getLocalUpdateSession()
These three methods return an XIS Session object.
TransactionHelper.commitSession() This method commits XIS and Oracle transactions. If a new Oracle transaction is needed, OracleBootstrap.newTransaction() must be called.
TransactionHelper.releaseSession() This method rolls back both the XIS and Oracle transactions if the XIS transaction has been been commited. Otherwise, it releases the XIS session and closes the Oracle connection.

A typical use of these methods might be:

  Session session = null;

  try {
    ReadWimConfiguration.processUsingDefaults();
    session = TransactionHelper.getLocalReadOnlySession();
    // do some XIS and Oracle work.
    TransactionHelper.commitSession();
  } catch (Exception e) {
    logger.fatal(e, e);
  } catch (Error e) {
    logger.fatal(e, e);
  } finally {
    TransactionHelper.releaseSession();
    System.out.println("Done.");
  }

Direct use of Oracle

If you only need to work with Oracle, you can directly use the OracleBootstrap class.

getConnection() This method needs to be called first. It will setup the DataSource object, if needed. A singleton Connection object is returned which is managed using the methods in OracleBootstrap. Thise connection has the AutoCommit option turned off.
addException() This method is called from within catch} blocks to register than an exception or error occured.
closeConnection() This method closes the Oracle connection and clears any caught exceptions (unless created by the close operation itself).
closeResultSet() This method closes the specified result set. It maskes the capture of exceptions thrown by the close operation.
closeStatement() This method closes the specified statement (prepared or otherwise). It maskes the capture of exceptions thrown by the close operation.
commitConnection() This method commits the connection but does not close it.
getExceptions() This method returns a copy of the collected exceptions.
hasExceptions() This method returns true of any exceptions have been collected.
newTransaction() This method starts a new transaction. It only needs to be called if you want to begin a new transaction after rolling back or commiting.
rollbackConnection() This method rolls back the connection but does not close it.

A typical use of these methods might be:

// The doIt() method does not commit nor rollback. It just handles the
// low-level SQL and exception handling.

public static void doIt() {
  Connection con = null;
  PreparedStatement ps = null;

  try {
    con = OracleBootstrap.getConnection();
    ps = con.prepareStatement("sql statement");
    // set parameters and execute query.
  } catch (Exception e) {
    OracleBootstrap.addException(e);
  } finally {
    OracleBootstrap.closeStatement(ps);
  }
  if (OracleBootstrap.hasExceptions()) {
    LogConfiguration.message(OracleBootstrap.getExceptions(), "some message");
  }
}

// This driver method need to be aware of the transaction. If an
// no exception occurs, the connection is commited. Otherwise, it
// is rolled back. In the finally clause, the connection is closed.
pubic static void foo() {
  try {
    doIt();
    OracleBootstrap.commitConnection();
  } catch (Exception e) {
    OracleBootstrap.rollbackConnection();
  } catch (Error e) {
    OracleBootstrap.rollbackConnection();
  } finally {
    OracleBootstrap.closeConnection();
}

Spring-mediated use of Oracle

The Spring framework has been around for quite some time. Since WorldSYNC v3.5 is making greater use of Oracle, I've explored existing frameworks instead of expanding the use of our homegrown JDBC-specific classes.

When using Spring has an mediator for Oracle, you should use the OracleBootstrap class. Its use is similar to that shown above except that some of the transaction handling is automated (you don't need to manually call the rollback method when an exception happens).

getDataSource() This method needs to be called first (instead of the getConnection() method). It will setup the DataSource object, if needed and start a new transaction.
addException() This method is called from within catch} blocks to register than an exception or error occured.
closeConnection() This method closes the Oracle connection and clears any caught exceptions (unless created by the close operation itself).
commitConnection() This method commits the connection but does not close it.
getExceptions() This method returns a copy of the collected exceptions.
hasExceptions() This method returns true of any exceptions have been collected.
newTransaction() This method starts a new transaction. It only needs to be called if you want to begin a new transaction after rolling back or commiting.

</p>A typical use of these methods might be:</p>

try {
  ReadWimConfiguration.processUsingDefaults();
  Spring01 a = new Spring01(OracleBootstrap.getDataSource());
  a.makeCachePoolFree("C05");
  OracleBootstrap.commitConnection();
} catch (Exception e) {
  NoOperation.noOp();
} catch (Error e) {
  NoOperation.noOp();
} finally {
  OracleBootstrap.closeConnection();
}

The rollback, if needed, is handled automatically when the connection is closed.