Monthly news review


Continuing the series on monthly, predominantly technological, news review…

CarPlay

iOS has arrived in the car, at least the premium car, not that it wasn’t there already. The experience is based around your iOS device and makes driving as distraction-free as possible.

Popcorn Times

Popcorn Times was born, died and re-born. Watching pirated movies online is nothing new, make it convenient and you’ve got a winner. What makes the application itself interesting is its use of Node-WebKit and peerflix.

Android Wear

No doubt now that Google is taking Android to wearables, starting with smartwatches. These days it looks like everyone is one-upping Apple, but somehow it ends up raking in all the profits.

WebScaleSQL

That’s a nerdy name for a new fork of MySQL that scales better.

Facebook buying Oculus VR

Looks like Facebook is making use of its cash reserves again. Earlier, they paid significantly more to buy WhatsApp.

Office for iPad

Lot’s of Office news this month, concluding with Microsoft launching Office for iPad. It is already top of charts in several countries. Earlier Microsoft launched a free OneNote app for Mac. I wonder which Office app is most useful, now that everyone concurs PowerPoints should be ditched.

ReadMill team acqhired by Dropbox

ReadMill was my favorite reading app for a while. Unfortunately, and especially on mobile, e-books are not easily ported to other apps.

Philips announces 4K TV with Android

TV makers have adopted widely divergent Smart TV OS strategies. LG has embraced WebOS. Samsung has embraced something akin to Chrome OS with support for HTML 5, Native Client, and WebGL. Will Android take over?

CorelDRAW Graphics Suite X7

CorelDRAW has announced the X7 iteration of their suite. The user interface has received a significant overhaul. Heavy users will encounter a crash every other day that will make them lose their work, that has not changed.

Quake III on Raspberry Pi using open source graphics driver

Last month Broadcom announced open source drivers for the GPU on Raspberry Pi. Simon Hall has thus claimed the bounty announced by Raspberry Pi Foundation. In unrelated news, Oxford Flood Network uses Raspberry Pi to monitor flooding levels. Interesting convergence of ideas such as smart cities, internet of things, and open hardware.

Advertisements

Graph Databases by Ian Robinson, Jim Webber, Emil Eifrem; O’Reilly Media


Graph Databases

This books lays a solid foundation for understanding what Graph Databases are all about. Implementation details are all based on Neo4J, except for a fleeting reference to Twitter’s FlockDB when discussing scalability.

Chapters 1 and 2 provide an overview of Graph Databases, and compare them to Relational and NoSQL Databases. Appendix A provides a useful overview of different NoSQL databases.

Data modeling with Graph Databases is compared to relational databases in Chapter 3. It also discusses the creation of domain models using an example from the Systems Management domain, and Cypher to create and query the models. Cross-domain modeling and common modeling pitfalls are also discussed.

Chapter 4 discusses data modeling for Neo4J in further detail, and demonstrates when to use nodes or relationships. Neo4J can be embedded into applications or deployed in server mode, benefits of each mode are discussed. Test-driven data model development with ImpermanentGraphDatabase Java class is also discussed.

Chapter 5 provides common real-world use cases and examples. Domains covered in detail include social networking, authorization and access control, and geo/logistics.

Chapter 6 discusses native graph processing and storage, with topics such as index-free adjacency for better query performance, and programmatic access to Neo4J database provided by the Kernel, Core, and Traverser APIs. Non-functional characteristics such as transactions (ACID properties), recoverability, availability, scale (capacity; latency; throughput) are also discussed.

Graph algorithms such as depth- and breath-first search, Dijkstra’s algorithm, and A* algorithm are discussed in chapter 7. Analyses based on these algorithms, and techniques from graph theory and social sciences, can be used to gain new insights from a domain. Social graph properties such as Triadic Closures, Structural Balance, and Local Bridges can be used to gain new insights into a social network.

I found the book extremely useful to understand what Graph Databases are all about.

I thank O’Reilly Media for providing the book for review.

Incremental upgrade of an embedded relational database


Several years ago I worked on a project that required incrementally upgrading an application and its embedded relational database. What follows is an overview of some best practices we used. Several open source projects, books and articles use or cite similar practices.

A full create script and incremental upgrade scripts

It is vital that you have a full create script for fresh installs, and an incremental upgrade script per application version. The create script has CREATE SQL statements mostly. The upgrade script mostly has ALTER statements, for the changes required from a version of the application to the next.

Maintain your scripts under version control

This ensures that you always know the changes that have been made, can rollback changes, and easily identify changes to create incremental update scripts.

Traceability between database scripts and application code

You should use the same label to tag the database scripts and the application code in the version control system, so you know which script versions match an application release.

Installation

The installer should upgrade the database from an older version of the application to the newest. You’ll need to have a procedure in place, a batch script for instance, that knows all application versions and can apply corresponding upgrade scripts in sequence.

Hibernate 2


What to me seems a long while back, I wrote an article on Hibernate. Spring was just beginning to take root, and everyone was raving about POJOs. I am studying Spring and Hibernate, and thought posting this bit of historical trivia would be a good starting point. Don’t use it as is, or use it at your own peril.

The ideal persistence mechanism

Ideally, objects would not need to be persisted if memory was non-volatile. Creating objects and establishing associations would suffice. Thus, a system would be a soup of objects, each having to deal with their own responsibilities, and not having to bother about external persistence.

O/R mapping

The closest we get to our ideal persistence is by using an O/R mapping framework such as Hibernate. Typically, external persistence is done by saving object state to relational databases. Thus, after we create an object, we have to persist it. The following steps are typically performed when a user interacts with a web based data entry use case:

  • Create new objects (transient) or query existing objects (persistent)
  • Begin a transaction
  • Change object properties and associations
  • Save objects to persistent storage
  • Commit the transaction

A simple persistence framework using Hibernate

In our architecture, development is driven by use cases. The flow of events of one or more use cases are orchestrated by a controller object. Each method of a controller object may initiate a new, or participate in an existing, database transaction. The controller saves and retrieves persistent objects using a Hibernate utility class, which in turn directly uses the Hibernate Session object.

import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.hibernate.CallbackException;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Interceptor;
import net.sf.hibernate.LockMode;
import net.sf.hibernate.ObjectNotFoundException;
import net.sf.hibernate.ReplicationMode;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.metadata.ClassMetadata;
import net.sf.hibernate.type.Type;

/**
 * This utility class provides a simple framework for using Hibernate
 * by implementing some <a href="http://www.hibernate.org/40.html">well known</a>
 * design patterns or by being useful with some of these patterns:
 *  - Thread Local session
 *  - AspectJ Hibernate aspect
 *  - Root Persistent Class
 *
 * In conjunctions with CGLIB and the TransactionConfiguration class it allows
 * any class to be extended so that methods of it's instances are wrapped with
 * appropriate begin and commit transaction invocations. The transaction
 * requirement can specified in an external xml configuration file.
 *
 * @see net.sf.hibernate.Session
 * @see net.sf.hibernate.SessionFactory
 */
public final class HibernateUtil implements MethodInterceptor, Interceptor {
// methods in various code snippets below
}

Persistent Objects

Persistent objects inherit from a common root class called PersistentObject as shown below.

/**
 * Super-class of all basic / entity classes.
 */
public abstract class PersistentObject implements Serializable {
    // flag indicating that object is persistent / saved
    private boolean _saved = false; 

    /**
     * This method is called when the object is saved to persistent
     * storage.
     */
    public void onSave() {
        _saved = true;
    }

    /**
     * This method is called when the object is loaded from persistent
     * storage.
     */
    public void onLoad() {
        _saved = true;
    }

    /**
     * This method is used to discover the saved status of the object.
     *
     * @return True if the object is exists in persistent storage
     */
    public boolean isSaved() {
        return _saved;
    }
}

Hibernate Utility needs the isSaved() method to hint a hibernate session on whether an object is persistent. This is required in the special case where the child object has the primary key of the parent object and not a direct reference to it. This is how the Hibernate utility, which needs to implement the Hibernate Interceptor interface, makes use of this method.

    /**
     * If the specified object is an instance of PersistentObject
     * sets the state of the object to saved.
     * @see net.sf.hibernate.Interceptor#onLoad(java.lang.Object,
     * java.io.Serializable, java.lang.Object[], java.lang.String[],
     * net.sf.hibernate.type.Type[])
     */
    public boolean onLoad(Object object, Serializable id, Object[] state,
            String[] propertyNames, Type[] types)
            throws CallbackException {

        if (object instanceof PersistentObject) {
            ( (PersistentObject) object ).onLoad();
        }
        return false; // we did not modify state
    }

    /**
     * If the specified object is an instance of AuditedPersistentObject
     * sets the dateLastUpdated attribute.
     */
    private boolean setDateLastUpdated(Object object, Object[] state,
            String[] propertyNames) {
        if (object instanceof AuditedPersistentObject) {
            for (int i = 0; i < propertyNames.length; i++) {
                if ("dateLastUpdated".equals(propertyNames[i])) {
                    state[i] = new Date();
                    return true;
                }
            }
        }
        return false; // we did not modify state
    }

    /**
     * @see net.sf.hibernate.Interceptor#onFlushDirty(java.lang.Object,
     * java.io.Serializable, java.lang.Object[], java.lang.Object[],
     * java.lang.String[], net.sf.hibernate.type.Type[])
     */
    public boolean onFlushDirty(Object object, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types)
            throws CallbackException {

        return setDateLastUpdated(object, currentState, propertyNames);
    }

    /**
     * @see net.sf.hibernate.Interceptor#onSave(java.lang.Object,
     * java.io.Serializable, java.lang.Object[], java.lang.String[],
     * net.sf.hibernate.type.Type[])
     */
    public boolean onSave(Object object, Serializable id, Object[] state,
            String[] propertyNames, Type[] types)
            throws CallbackException {

        boolean result = setDateLastUpdated(object, state, propertyNames);

        if (object instanceof PersistentObject) {
            ( (PersistentObject) object ).onSave();
        }

        return result;
    }

    /** (non-Javadoc)
     * @see net.sf.hibernate.Interceptor#onDelete(java.lang.Object,
     * java.io.Serializable, java.lang.Object[], java.lang.String[],
     * net.sf.hibernate.type.Type[])
     */
    public void onDelete(Object object, Serializable id, Object[] state,
            String[] propertyNames, Type[] types)
            throws CallbackException {
    }

    /** (non-Javadoc)
     * @see net.sf.hibernate.Interceptor#preFlush(java.util.Iterator)
     */
    public void preFlush(Iterator objects) throws CallbackException {

    }

    /** (non-Javadoc)
     * @see net.sf.hibernate.Interceptor#postFlush(java.util.Iterator)
     */
    public void postFlush(Iterator objects) throws CallbackException {

    }

    /**
     * If the object is a PersistentObject returns its saved status.
     * @return true if the PersistentObject already exists in the database.
     * @see net.sf.hibernate.Interceptor#isUnsaved(java.lang.Object)
     */
    public Boolean isUnsaved(Object object) {
        if (object instanceof PersistentObject) {
            return new Boolean( !( (PersistentObject) object ).isSaved() );
        } else {
            return null; // let Hibernate assume default behavior
        }
    }

    /**
     * @see net.sf.hibernate.Interceptor#findDirty(java.lang.Object,
     * java.io.Serializable, java.lang.Object[], java.lang.Object[],
     * java.lang.String[], net.sf.hibernate.type.Type[])
     */
    public int[] findDirty(Object object, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        return null; // let Hibernate assume default behavior
    }

    /**
     * @see net.sf.hibernate.Interceptor#instantiate(java.lang.Class,
     * java.io.Serializable)
     */
    public Object instantiate(Class classObj, Serializable id)
            throws CallbackException {
        Object object = null; // let Hibernate assume default behavior
        return object;
    }

Persistent objects that have composite keys must also override the equals and hashCode methods. The equals method must return true if the corresponding primary key attributes of two objects of the same class pass the equals test.

Intercepting objects about to be saved

The onSave method shown in the previous code listing also forms the basis for making changes to objects before they are saved. In our case we need to update the time the object was lasted updated. We have done that by creating a base class called AuditedPersistentObject, for all objects that need this new attribute. The implementation of this class is shown below. In the onSave method of Hibernate Utility we detect whether the object is an instance of this class and set the dateLastUpdated attribute.

/**
 * This class and it's sub-classes represent persistent objects with
 * audit information such as the date/hour the object was last updated.
 */
public abstract class AuditedPersistentObject extends PersistentObject {
    protected Date dateLastUpdated = null;

    /**
     * Recover the date/hour of last update.
     * @return Date/Hour
     */
    public Date getDateLastUpdated() {
        return dateLastUpdated;
    }

    /**
     * Set the date/hour of last update.
     * @param dateLastUpdated Date/hour
     */
    public void setDateLastUpdated(Date dateLastUpdated) {
        this.dateLastUpdated = dateLastUpdated;
    }
}

Declarative transactions

As mentioned previously, the methods in the controller can initiate transactions. To do this declaratively, we create every controller object using the following method of Hibernate Utility.

    /***
     * This method returns a CGLIB extended object of the
     * specified class. Each method call on the extended object
     * results in a callback to the intercept method.
     * @param c The class to extend.
     * @return A new extended instance of the specified class
     */
    public Object extendClass(Class c) {
        Object newObject = null;
        newObject = Enhancer.create(c, null, this);
        return newObject;
    }

Now, when any method of the controller is called, the intercept method of Hibernate Utility is called automatically. For this, Hibernate Utility must implement the net.sf.cglib.proxy.MethodInterceptor interface of CGLIB. The intercept method itself, and all the other methods it calls, and the attributes they use, are shown below.

    // Private attributes

    // Transaction configuration
    private TransactionConfiguration transactions;
    // Hibernate Session Factory
    private SessionFactory sessionFactory = null;
    // Number of transactions in progress
    private int transactionCount = 0;             

    // Private Thread Local attributes

    // Session local to current thread
    private ThreadLocal session = new ThreadLocal();
    // Active transaction local to current thread
    private ThreadLocal transaction = new ThreadLocal();
    // Depth of the active database transaction
    private ThreadLocal transactionDepth = new ThreadLocal(); 

    /**
     * Wraps the call of an intercepted method with begin and
     * commit transactions if it supports transactions.
     * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy)
     */
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {

            boolean useTransaction;
            Object retValFromSuper = null;

            useTransaction = transactions.isTransaction(method);
            try {
                if (useTransaction) beginTransaction();

                retValFromSuper = proxy.invokeSuper(obj, args);

                if (useTransaction) commitTransaction();

            }catch (Throwable e) {
                if (useTransaction) rollbackTransaction();
                throw e;
            }
            return retValFromSuper;
    }

    /**
     * Initiates a new database transaction and associates the
     * Hibernate Transaction instance with the current thread only on the
     * first call to this method. Successive calls to this method will
     * not initiate any transactions and result in incrementing a
     * stack counter. This stack counter is later used to determine
     * the outer-most commit so that the transaction can be committed.
     *
     * @throws DataPersistenceException If the beginTransaction method
     * of hibernate returns a HibernateException.
     */
    public void beginTransaction() throws DataPersistenceException {
        Integer depth = (Integer) transactionDepth.get();
        if (depth == null) {
            // first call to begin transaction in this thread
            Session s = (Session) session.get();
            if (s == null) {
                currentSession();
            }
            s = (Session) session.get();
            try {
                Transaction t = (Transaction) s.beginTransaction();
                transaction.set(t);
                transactionDepth.set(new Integer(0));
                incrementTransactionCount();
            } catch (HibernateException e) {
                throw new DataPersistenceException(e);
            }
        } else {
            // increment depth
            transactionDepth.set(new Integer(depth.intValue() + 1));
        }
    }

    /**
     * Commits a database transaction and dissociates the
     * Hibernate Transaction instance associated with the
     * current thread only if this is the outer-most commit request.
     *
     * @throws DataPersistenceException If the commit method
     * of hibernate returns a HibernateException or there is
     * no existing transaction to be committed.
     */
    public void commitTransaction() throws DataPersistenceException {
        Integer depth = (Integer) transactionDepth.get();
        if (depth == null) {
            // no begin transaction issued
        } else {
            if (depth.intValue() == 0) {
                // reached the outer most call to begin transaction
                Transaction t = (Transaction) transaction.get();
                if (t == null) {
                    // no begin transaction issued or rolled back
                    throw new DataPersistenceException("Assertion Failed: A transaction should be present but was not found.", null);
                } else {
                    try {
                        t.commit();
                    } catch (HibernateException e) {
                        throw new DataPersistenceException(e);
                    } finally {
                        transaction.set(null);
                        transactionDepth.set(null);
                        decrementTransactionCount();
                    }
                }
            } else {
                // decrement depth, ignore commit request
                transactionDepth.set(new Integer(depth.intValue() - 1));
            }
        }
    }

    /**
     * Rolls back a database transaction and dissociates the
     * Hibernate Transaction instance associated with the
     * current thread.
     *
     * @throws DataPersistenceException If the rollback method
     * of hibernate returns a HibernateException or there is
     * no existing transaction to be rolled back.
     */
    public void rollbackTransaction() throws DataPersistenceException {
        Integer depth = (Integer) transactionDepth.get();
        if (depth == null) {
            // no begin transaction issued
        } else {
            Transaction t = (Transaction) transaction.get();
            if (t == null) {
                // no transaction
                throw new DataPersistenceException("Assertion Failed: A transaction should be present but was not found.", null);
            } else {
                try {
                    t.rollback();
                } catch (HibernateException e) {
                    throw new DataPersistenceException(e);
                } finally {
                    transaction.set(null);
                    decrementTransactionCount();
                    closeSession();
                }
            }
            // decrement depth
            transactionDepth.set(null);
        }
    }

    /**
     * Recovers a Hibernate session associated with the current thread.
     * Opens a new session if one doesn't already exist and associates
     * it to the thread. As long as you don't call the closeSession
     * or the rollbackTransaction methods the session remains
     * open and associated with the current thread.
     *
     * @return A Hibernate session
     *
     * @throws DataPersistenceException If the openSession method
     * of the Hibernate session factory fails.
     */
    public Session currentSession() throws DataPersistenceException {

        Session s = (Session) session.get();
        // Open a new Session, if this Thread has none yet
        if (s == null) {
            try {
                s = sessionFactory.openSession(this);
                session.set(s);
            } catch (HibernateException e) {
                e.printStackTrace();
                throw new DataPersistenceException(e);
            }
        }
        return s;
    }

    /**
     * Closes and dissociates the Hibernate session associated with
     * the current thread.
     * @throws DataPersistenceException If the close method of the
     * Hibernate session fails.
     */
    public void closeSession() throws DataPersistenceException {
        Integer depth = (Integer) transactionDepth.get();
        if (depth != null) {
            // We are within a transaction, ignore close request
        } else {
            try {
                Session s = (Session) session.get();
                session.set(null);
                if (s != null) {
                    s.close();
                }
            } catch (HibernateException e) {
                e.printStackTrace();
                throw new DataPersistenceException(e);
            }
        }
    }

The TransactionConfiguration class, used in the intercept method above, parses an XML file that specifies which methods of any class need database transactions. The isTransaction methods of this class return true for methods that need database transactions. See the code listing below for implementation of these methods.

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Utility class used to represent transaction configuration.
 */
public class TransactionConfiguration extends DefaultHandler {
    private static String className;
    Map classes = new HashMap();
    private static TransactionConfiguration instance;

    public static TransactionConfiguration getInstance() {
        if (instance == null) {
            instance = new TransactionConfiguration();
        }
        return instance;
    }

    /**
     * The method returns true if the method of the specified class is
     * transactional.
     *
     * @param className
     *            Fully qualified name of the class
     * @param methodName
     *            Method name
     * @return true if the method is specified as transactional.
     */
    public boolean isTransaction(String className, String methodName) {
        return hasMethod(className, methodName);
    }

    /**
     * The method returns true if the given Method instance is transactional.
     *
     * @param method
     *            Method instance
     * @return true if the Method instance is specified as transactional.
     */
    public boolean isTransaction(Method method) {
        boolean val;
        val = isTransaction(method.getDeclaringClass().getName(), method
                .getName());
        if (val == false) {
            // let us check if super classes / interfaces are transactions
            for (int i = 0; i < method.getDeclaringClass().getInterfaces().length; i++) {
                val = isTransaction(
                        method.getDeclaringClass().getInterfaces()[i].getName(),
                        method.getName());
                if (val == true)
                    break;
            }
        }
        return val;
    }

Hibernate Utility encapsulates the most commonly used Hibernate Session and SessionFactory methods, so you don’t need to obtain a Session by calling the currentSession method and call the methods of the Session.

Declarative transactions using AspectJ

The following aspect can be used to extend desired methods to add declarative transactions.

public abstract aspect TransactionAspect {

    public abstract pointcut transactedMethods();

    Object around() throws SystemRuntimeException : transactedMethods() {
        boolean useTransaction = false;
        Object retValFromSuper = null;

        String methodName = thisJoinPoint.getSignature().getName();
        String className = thisJoinPoint.getSignature()
                .getDeclaringType().getName();

        // The TransactionConfiguration determines if a method
        // should be made transactional or not.
        useTransaction = TransactionConfiguration.getInstance()
                .isTransaction(className, methodName);

        if ( useTransaction ) {
            System.out.println("TransactionAspect: Method '"
                    + className + "." + methodName
                    + "' is transactional.");
            try {
                // begin the transaction.
                HibernateUtil.getInstance().beginTransaction();

                // "proceed()" allows the method to continue as it normally
                // would. The return value is saved.
                retValFromSuper = proceed();

                HibernateUtil.getInstance().commitTransaction();

                return retValFromSuper;
            } catch (RuntimeException e) {
                System.out.println("TransactionAspect: Method '"
                        + className + "." + methodName
                        + "' threw an exception.");
                HibernateUtil.getInstance().rollbackTransaction();
                throw e;
            }
        }

        // This means the method was not transactional.
        System.out.println("TransactionAspect: Method '"
                + className + "." + methodName
                + "' is NOT transactional.");

        // Return the result of the action method as normal.
        return proceed();
    }
}

A concrete aspect must extend the abstract aspect above and implement the abstract join point transactedMethods as follows.

public aspect AppTransactionAspect extends TransactionAspect {
    public pointcut transactedMethods() :
        (target(PersistentObject)
        || target(SomeOtherClass))
        && execution(public * *( .. ))
        && !execution(* PersistentObject.*( .. ))
        && !execution(public * find*( .. ))
        && !execution(public * get*( ))
        && !execution(public * set*( .. ));
}

The transactedMethods point cut implementation above executes the around advice implemented in the abstract aspect, for all methods of classes that are sub classes of SomeOtherClass and PersistentObject, except the following:

  • All methods of the class PersistentObject itself.
  • All methods beginning with set.
  • All methods beginning with get.
  • All methods beginning with find.

Concurrency

While an object is being prepared for updating, the persistent representation of the object in the database may be changed by another transaction. Hibernate automatically adds version number checking to all UPDATE commands if the class mapping has a version element, as shown below.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping package="test.app">

    <class name="Customer" table="CUSTOMER">

        <id name="id">
            <column name="id" sql-type="integer" not-null="true"/>
            <generator class="native"/>
        </id>

        <version name="version" column="version" type="integer" />

        <property name="name">
            <column name="name" sql-type="varchar(20)" not-null="true"/>
        </property>

        <bag name="orders" table="ORDER" cascade="all">
            <key column="customer_id"/>
            <one-to-many class="Order"/>
        </bag>

    </class>

</hibernate-mapping>

The application is responsible for checking that the object information it has is not stale, before updating the object.

Closing Hibernate sessions

Closing hibernate sessions is a must to liberate JVM heap and avoid an OutOfMemoryError, and more importantly, close database connections. In web applications one useful strategy is to use a servlet filter to close a Hibernate session as shown below.

public class CloseDataSession implements Filter {

    private static ThreadLocal stackCounter = new ThreadLocal();
        // for closing sessions only when exiting from a client request

    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        try {
            increment();
            chain.doFilter(req, resp);
        } finally {
            if (decrement() <= 0) {
                HibernateUtil.getInstance().closeSession();
            }
        }
    }

    public void init(FilterConfig config) throws ServletException {
    }

    private int increment() {
        int count = 0;
        if (stackCounter.get() == null) {
            stackCounter.set(new Integer(++count));
        } else {
            count = ((Integer) stackCounter.get()).intValue();
            stackCounter.set(new Integer(++count));
        }
        return count;
    }

    private int decrement() {
        int count = 0;
        if (stackCounter.get() == null) {
            stackCounter.set(new Integer(count));
        } else {
            count = ((Integer) stackCounter.get()).intValue();
            stackCounter.set(new Integer(--count));
        }
        return count;
    }
}

The filter CloseDataSession is mapped to all server side resources that directly or indirectly access any persistent objects. This mapping is done in the web module descriptor (web.xml) of a J2EE web application. Some application servers execute a filter several times within the same web request, for example, every time when the request is forwarded. To close the Hibernate session only once, we use a simple filter execution counter associated with the current thread. Only when the counter goes to zero do we close the session.

For those adopting Hibernate today

I recommend using Hibernate with JPA, or Spring, and using annotations instead of manually coding configuration files.

SQL Server deadlock


You have written a very useful enterprise application. All of a sudden users complain that data they entered is lost. You hurriedly start taking a look at the SQL Server log or run a trace using SQL Profiler, and see the dreaded message:

Error 1205 : Transaction (Process ID) was deadlocked on resources with another process 
and has been chosen as the deadlock victim. Rerun the transaction.

Quite obviously your code does not expect this error and does not rerun that transaction. You start analyzing the deadlock scenario, if you can reproduce it. After a while you reach the conclusion that you just can’t change anything in those complex stored procedures that write data to the database.

In this particular scenario, one solution that did help me was to lock the entire table using TABLOCK or TABLOCKX. It might seems like something really drastic to do, but if you have long running procedures, that hopefully do not exceed the timeout period of your database transaction, then it can be one quick-fix alternative.

You can use the NOLOCK hint on other SELECT queries so that they don’t wait for your transaction to be committed, before returning useful results.

The long term solution is obviously more elaborate. You can:

  • Optimize you queries or redesign your code (and requirements) so that the transaction time is as short as possible
  • Detect transaction failures and rerun the transaction again
  • Run long transactions at programmed downtimes