Plug-ins para gestionar los sucesos del ciclo de vida de transacciones

Utilice el plug-in TransactionCallback para personalizar las operaciones de creación de versiones y de comparación de los objetos de la memoria caché cuando se utiliza la estrategia de bloqueo optimista.

Puede proporcionar un objeto de devolución de llamada optimista conectable que implementa la interfaz com.ibm.websphere.objectgrid.plugins.OptimisticCallback. Para las correlaciones de entidades, se configura automáticamente un plug-in OptimisticCallback de alto rendimiento.

Finalidad

Utilice la interfaz OptimisticCallback para proporcionar operaciones de comparación optimista para los valores de una correlación. Es necesaria una implementación OptimisticCallback cuando se utiliza la estrategia de bloqueo optimista. WebSphere eXtreme Scale proporciona una implementación predeterminada de OptimisticCallback. Sin embargo, normalmente la aplicación debe conectar su propia implementación de la interfaz OptimisticCallback. Consulte Estrategias de bloqueo para obtener más información.

Implementación predeterminada

La infraestructura de eXtreme Scale proporciona una implementación predeterminada de la interfaz OptimisticCallback que se utiliza si la aplicación no se conecta a un objeto OptimisticCallback proporcionado por la aplicación, tal como se demuestra en la sección anterior. La implementación predeterminada siempre devuelve el valor especial de NULL_OPTIMISTIC_VERSION como el objeto de versión del valor y nunca actualiza el objeto de versión. Esta acción realiza una comparación optimista, una operación sin función. En la mayoría de los casos, no desea que se produzca la función sin operación al utilizar la estrategia de bloqueo optimista. Las aplicaciones deben implementar la interfaz OptimisticCallback y conectar sus propias implementaciones de OptimisticCallback, de forma que no se utilice la implementación predeterminada. Sin embargo, como mínimo, existe un escenario donde resulta práctica la implementación proporcionada predeterminada de OptimisticCallback. Observe la situación siguiente:
  • Se conecta un cargador para la correlación de respaldo.
  • El cargador sabe cómo realizar la comparación optimista sin ayuda de un plug-in OptimisticCallback.
¿Cómo puede saber el cargador cómo tratar con la creación de versiones optimista sin la ayuda de un objeto OptimisticCallback? El cargador conoce el objeto de clase de valor y sabe qué campo del objeto de valor se utiliza como valor de creación de versiones optimista. Por ejemplo, imagine que se utiliza la interfaz siguiente para el objeto de valor de la correlación de empleados.
public interface Employee
{
    // Número de secuencia utilizado para la creación de versiones optimista.
    public long getSequenceNumber();
    public void setSequenceNumber(long newSequenceNumber);
    // Otros métodos get/set para otros campos del objeto Employee.
}

En este caso, el cargador sabe que puede utilizar el método getSequenceNumber para obtener la información de creación de versiones actual para un objeto de valor Employee. El cargador incrementa el valor devuelto para generar un nuevo número de versión antes de actualizar el almacenamiento persistente con el nuevo valor Employee. Para un cargador JDBC (Java Database Connectivity), se utiliza el número de secuencia actual en la cláusula where de una sentencia de actualización sobrecualificada de SQL y utiliza el nuevo número de secuencia generado para establecer la columna del número de secuencia en el nuevo valor de número de secuencia.

Otra posibilidad es que el cargador utilice una función, que proporciona el programa de fondo, que actualiza automáticamente una columna oculta que puede utilizarse para la creación de versiones optimista. En algunos casos, puede usarse un procedimiento almacenado o un desencadenante para ayudar a mantener una columna que contiene la información sobre la creación de versiones. Si el cargador utiliza una de estas técnicas para mantener la información de la creación de versiones optimista, la aplicación no necesita proporcionar una implementación OptimisticCallback. Puede utilizar la implementación predeterminada de OptimisticCallback porque el cargador puede manejar la creación de versiones optimista sin la ayuda de un objeto OptimisticCallback.

Implementación predeterminada de entidades

Las entidades se almacenan en ObjectGrid mediante objetos de tuple. La implementación predeterminada de OptimisticCallback se comporta del mismo modo que el comportamiento para las correlaciones sin entidad. Sin embargo, el campo de versión de la entidad se identifica a través del uso de la anotación @Version o el atributo de versión en el archivo XML de descriptor de la entidad.

El atributo de versión puede ser de uno de los tipos siguientes: int, Integer, short, Short, long, Long o java.sql.Timestamp. Una entidad debe tener sólo un atributo de versión definido. El atributo de versión sólo se debe establecer durante la construcción. Después de persistir la entidad, el valor del atributo de versión no se debe modificar.

Si no se configura el atributo de versión y se utiliza la estrategia de bloqueo optimista, se crea una versión implícitamente de todo el tuple utilizando el estado completo del tuple.

En el ejemplo siguiente, la entidad Employee tiene un atributo de versión de tipo long denominado SequenceNumber:
@Entity
public class Employee
{
private long sequence;
    // Número de secuencia utilizado para la creación de versiones optimista.
    @Version
    public long getSequenceNumber() {
        return sequence;
    }
    public void setSequenceNumber(long newSequenceNumber) {
        this.sequence = newSequenceNumber;
    }
    // Otros métodos get/set para otros campos del objeto Employee.
}

Escritura de una implementación de OptimisticCallback

Una implementación de OptimisticCallback debe implementar la interfaz OptimisticCallback y seguir los convenios comunes de plug-in de ObjectGrid

La siguiente lista proporciona una descripción o una consideración para cada uno de los métodos de la interfaz OptimisticCallback:

NULL_OPTIMISTIC_VERSION

Este valor especial es devuelto por el método getVersionedObjectForValue si se utiliza la implementación predeterminada de OptimisticCallback, en lugar de una predeterminado de OptimisticCallback proporcionada por la aplicación.

Método getVersionedObjectForValue

El método getVersionedObjectForValue podría devolver una copia del valor, o podría devolver un atributo del valor que se puede utilizar para la creación de versiones. Este método se llama siempre que se asocia un objeto con una transacción. Cuando no se establece ningún cargador en una correlación de respaldo, la correlación de respaldo utiliza este valor en la fase de confirmación para realizar una comparación de versiones optimista. La correlación de respaldo utiliza la comparación de versiones optimista para garantizar que la versión no ha cambiado desde la primera vez que esta transacción accedió a la entrada de correlación modificada por esta transacción. Si otra transacción hubiera modificado la versión de esta entrada de correlación, se produciría una anomalía en la comparación de versiones y la correlación de respaldo mostraría una excepción OptimisticCollisionException que forzaría la retrotracción de la transacción. Si hay un cargador conectado, la correlación de respaldo no utiliza la información de creación de versiones optimista. En su lugar, el cargador deberá realizar una comparación de versiones optimista y actualizar la información de la creación de versiones cuando sea necesario. Normalmente, el cargador obtiene el objeto inicial de la creación de versiones del LogElement pasado al método batchUpdate en el cargador, que se llama cuando se produce una operación de vaciado o cuando se confirma una transacción.

El código siguiente muestra la implementación que utiliza el objeto EmployeeOptimisticCallbackImpl:
public Object getVersionedObjectForValue(Object value)
{
    if (value == null)
    {
        return null;
    }
    else
    {
        Employee emp = (Employee) value;
        return new Long( emp.getSequenceNumber() );
    }
}

Tal como se ha demostrado en el ejemplo anterior, el atributo sequenceNumber se devuelve en un objeto java.lang.Long tal como esperaba el cargador, que implica que la misma que escribió el cargador, también escribió la implementación de EmployeeOptimisticCallbackImpl, o bien trabajó estrechamente con la persona que implementó la implementación de EmployeeOptimisticCallbackImpl. Por ejemplo, estas personas acordaron el valor devuelto por el método getVersionedObjectForValue. Tal como se ha descrito previamente, la implementación predeterminada de OptimisticCallback devuelve el valor especial NULL_OPTIMISTIC_VERSION como el objeto de la versión.

Método updateVersionedObjectForValue

Se llama al método updateVersionedObjectForValue cuando una transacción ha actualizado un valor y es necesario un nuevo objeto de versión. Si el método getVersionedObjectForValue devuelve un atributo del valor, este método suele actualizar el valor de atributo con un nuevo objeto de versión. Si el método getVersionedObjectForValue devuelve una copia del valor, este método normalmente no se actualiza. El OptimisticCallback predeterminado no se actualiza porque la implementación predeterminada del método getVersionedObjectForValue siempre devuelve el valor especial NULL_OPTIMISTIC_VERSION como el objeto de versión. El siguiente ejemplo muestra la implementación utilizada por el objeto EmployeeOptimisticCallbackImpl que se utiliza en la sección OptimisticCallback:
public void updateVersionedObjectForValue(Object value)
{
    if ( value != null )
    {
        Employee emp = (Employee) value;
        long next = emp.getSequenceNumber() + 1;
        emp.updateSequenceNumber( next );
    }
}

Como se demuestra en el ejemplo anterior, el atributo sequenceNumber se incrementa por uno, de forma que la próxima vez que se llame al método getVersionedObjectForValue, el valor java.lang.Long devuelto tiene un valor largo que es el valor de número de secuencia original. Más de uno, por ejemplo, es el siguiente valor de versión para esta instancia de empleado. De nuevo, este ejemplo implica que la misma persona que escribió el cargador escribió EmployeeOptimisticCallbackImpl o colaboró con la persona que implementó EmployeeOptimisticCallbackImpl.

Método serializeVersionedValue

Este método escribe el valor con versión en la corriente especificada. En función de la implementación, el valor con versión puede utilizarse para identificar colisiones de actualización optimista. En algunas implementaciones, el valor con versión es una copia del valor original. Otras implementaciones podrían tener un número de secuencia o algún otro objeto para indicar la versión del valor. Puesto que se desconoce la implementación real, este método se proporciona para realizar la serialización correcta. La implementación predeterminada llama al método writeObject.

Método inflateVersionedValue

Este método toma la versión serializada del valor con versión y devuelve el objeto de valor con versión real. En función de la implementación, el valor con versión puede utilizarse para identificar colisiones de actualización optimista. En algunas implementaciones, el valor con versión es una copia del valor original. Otras implementaciones podrían tener un número de secuencia o algún otro objeto para indicar la versión del valor. Puesto que la implementación real se desconoce, se proporciona este método para realizar la deserialización adecuada. La implementación predeterminada llama al método readObject.

Utilización de una implementación de OptimisticCallback proporcionada por la aplicación

Tiene dos enfoques para añadir un OptimisticCallback proporcionado por la aplicación en la configuración de BackingMap: configuración mediante programa y configuración de XML.

Conexión mediante programación de una implementación de OptimisticCallback

El siguiente ejemplo demuestra cómo una aplicación puede conectar mediante programación un objeto OptimisticCallback para la correlación de respaldo de empleado en la instancia del ObjectGrid grid1:
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.BackingMap;
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectGrid og = ogManager.createObjectGrid( "grid1" );
BackingMap bm = dg.defineMap("employees");
EmployeeOptimisticCallbackImpl cb = new EmployeeOptimisticCallbackImpl();
bm.setOptimisticCallback( cb );

Enfoque de configuración de XML para conectar una implementación de OptimisticCallback

El objeto EmployeeOptimisticCallbackImpl del ejemplo anterior debe implementar la interfaz OptimisticCallback. La aplicación también puede utilizar un archivo XML para conectar su objeto OptimisticCallback tal como se muestra en el siguiente ejemplo:
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
    <objectGrid name="grid1">
        <backingMap name="employees" pluginCollectionRef="employees" lockStrategy="OPTIMISTIC" />
    </objectGrid>
</objectGrids>

<backingMapPluginCollections>
    <backingMapPluginCollection id="employees">
        <bean id="OptimisticCallback" className="com.xyz.EmployeeOptimisticCallbackImpl" />
    </backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>