Use o plug-in TransactionCallback para customizar as operações de versão e de comparação de objetos do cache ao usar a estratégia de bloqueio otimista.
É possível fornecer um objeto de retorno de chamada otimista conectável que implementa a interface com.ibm.websphere.objectgrid.plugins.OptimisticCallback. Para os mapas de entidade, um plug-in OptimisticCallback de alto desempenho é automaticamente configurado.
Utilize a interface OptimisticCallback para fornecer operações de comparação otimistas para os valores de um mapa. Uma implementação OptimisticCallback é necessária ao utilizar a estratégia de bloqueio otimista. O WebSphere eXtreme Scale fornece uma implementação OptimisticCallback padrão. No entanto, geralmente o aplicativo deve conectar sua própria implementação da interface OptimisticCallback. Consulte o Estratégias de Bloqueio para obter informações adicionais.
public interface Employee
{
// Sequential sequence number used for optimistic versioning.
public long getSequenceNumber();
public void setSequenceNumber(long newSequenceNumber);
// Other get/set methods for other fields of Employee object.
}
Neste caso, o utilitário de carga sabe que pode utilizar o método getSequenceNumber para obter as informações de versão atuais para um objeto de valor Employee. O utilitário de carga incrementa o valor retornado para gerar um novo número de versão antes de atualizar o armazenamento persistente com o novo valor Employee. Para um utilitário de carga do JDBC (Java Database Connectivity), o número de sequência atual na cláusula where de uma instrução update SQL super qualificada é usado, e ele usa o novo número de sequência gerado para configurar a coluna de número de sequência ao novo valor de número de sequência.
Outra possibilidade é que o utilitário de carga faça uso de alguma função fornecida por backend que atualiza automaticamente uma coluna oculta que pode ser utilizada para versões otimistas. Em alguns casos, um procedimento armazenado ou acionador possivelmente pode ser utilizado para ajudar a manter uma coluna que contém informações de controle de versões. Se o utilitário de carga estiver utilizando uma destas técnicas para a manutenção de informações de versões otimistas, então, o aplicativo não precisa fornecer uma implementação do OptimisticCallback. A implementação padrão OptimisticCallback pode ser utilizada porque o utilitário de carga consegue identificar versões otimistas sem nenhuma assistência de um objeto OptimisticCallback.
As entidades são armazenadas no ObjectGrid utilizando objetos de tupla. A implementação padrão do OptimisticCallback se comporta da mesma maneira que se comporta com mapas de não-entidade. Entretanto, o campo de versão na entidade é identificado utilizando a anotação @Version ou o atributo version no arquivo XML descritor da entidade.
O atributo version pode ser de um dos seguintes tipos: int, Integer, short, Short, long, Long ou java.sql.Timestamp. Uma entidade deve ter somente um atributo de versão definido. O atributo de versão deve ser configurado somente durante a construção. Depois de a entidade ser persistida, o valor do atributo de versão não deve ser modificado.
Se um atributo de versão não estiver configurado e a estratégia de bloqueio optimistic for usada, então toda a tupla assume implicitamente a versão usando o estado completo da tupla.
@Entity
public class Employee {
private long sequence;
// Sequential sequence number used for optimistic versioning.
@Version
public long getSequenceNumber() {
return sequence;
}
public void setSequenceNumber(long newSequenceNumber) {
this.sequence = newSequenceNumber;
}
// Other get/set methods for other fields of Employee object.
}
Uma implementação OptimisticCallback precisa implementar a interface OptimisticCallback e seguir as convenções comuns do plug-in ObjectGrid.
A lista a seguir fornece uma descrição ou consideração para cada um dos métodos na interface OptimisticCallback:
Este valor especial será retornado pelo método getVersionedObjectForValue se a implementação OptimisticCallback padrão for utilizada em vez de uma implementação OptimisticCallback fornecida pelo aplicativo.
O método getVersionedObjectForValue pode retornar uma cópia do valor ou pode retornar um atributo do valor que pode ser utilizado para fins de controle de versões. Este método é chamado sempre que um objeto é associado a uma transação. Quando nenhum utilitário de carga é configurado em um mapa de apoio, o mapa de apoio usa este valor no momento da consolidação para executar uma comparação de versão optimistic. A comparação de versão otimista é utilizada pelo mapa de suporte para assegurar que a versão não tenha sido alterada desde que esta transação acessou pela primeira vez a entrada do mapa que foi modificada por esta transação. Se outra transação já tiver modificado a versão desta entrada do mapa, a comparação de versão falhará e o mapa de suporte exibirá uma exceção OptimisticCollisionException para forçar o rollback da transação. Se um Utilitário de Carga estiver conectado, o mapa de suporte não utilizará as informações de controle de versões otimista. Em vez disso, o Utilitário de Carga é responsável por desempenhar a comparação de controle de versões otimista e por atualizar as informações de controle de versões quando necessário. O Utilitário de Carga geralmente obtém o objeto de controle de versões inicial do LogElement transmitido para o método batchUpdate no Utilitário de Carga, que é chamado quando ocorre uma operação de limpeza ou uma transação é confirmada.
public Object getVersionedObjectForValue(Object value)
{
if (value == null)
{
return null;
}
else
{
Employee emp = (Employee) value;
return new Long( emp.getSequenceNumber() );
}
}
Conforme demonstrado no exemplo anterior, o atributo sequenceNumber é retornado em um objeto java.lang.Long conforme esperado pelo Utilitário de Carga, que significa que a mesma pessoa que gravou o Utilitário de Carga gravou a implementação de EmployeeOptimisticCallbackImpl ou trabalhou junto com a pessoa que implementou EmployeeOptimisticCallbackImpl. Por exemplo, essas pessoas concordam com o valor que é retornado pelo método getVersionedObjectForValue. Conforme descrito anteriormente, a implementação OptimisticCallback padrão retorna o valor especial NULL_OPTIMISTIC_VERSION como o objeto de versão.
public void updateVersionedObjectForValue(Object value)
{
if ( value != null )
{
Employee emp = (Employee) value;
long next = emp.getSequenceNumber() + 1;
emp.updateSequenceNumber( next );
}
}
Conforme demonstrado no exemplo anterior, o atributo sequenceNumber é incrementado em um para que, na próxima vez o método getVersionedObjectForValue for chamado, o valor java.lang.Long retornado tenha um valor longo que seja o valor do número de sequência original. Mais um, por exemplo, é o próximo valor de versão para esta instância de funcionário. Novamente, este exemplo significa que a mesma pessoa que gravou o Utilitário de Carga gravou a implementação EmployeeOptimisticCallbackImpl ou trabalhou junto com a pessoa que implementou o EmployeeOptimisticCallbackImpl.
Este método grava o valor com versão no fluxo especificado. Dependendo da implementação, o valor com versão pode ser utilizado para identificar colisões de atualização otimistas. Em algumas implementações, o valor com versão é uma cópia do valor original. Outras implementações podem ter um número de sequência ou algum outro objeto para indicar a versão do valor. Como a implementação real é desconhecida, este método é fornecido para executar a serialização apropriada. A implementação padrão faz uma chamada writeObject.
Este método utiliza a versão serializada do valor com versão e retorna o objeto de valor com versão real. Dependendo da implementação, o valor com versão pode ser utilizado para identificar colisões de atualização otimistas. Em algumas implementações, o valor com versão é uma cópia do valor original. Outras implementações podem ter um número de sequência ou algum outro objeto para indicar a versão do valor. Como a implementação real é desconhecida, este método é fornecido para desempenhar a desserialização apropriada. A implementação padrão chama o método readObject.
Há duas abordagens para incluir uma implementação OptimisticCallback fornecido pelo aplicativo na configuração de BackingMap: configuração programática e configuração 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>