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.
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.
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.
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.
@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.
}
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:
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.
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.
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.
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.
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.
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.
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.
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 );
<?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>