Más detalles sobre ConcurrentAccessException: según la especificación EJB, la aplicación sincroniza el acceso a SLSB. servidor. Sin embargo, este no es el caso con SFSB. La carga de asegurarse de que no se acceda al SFSB simultáneamente está en los hombros del desarrollador de la aplicación.
¿Por qué? Bueno, la sincronización de SLSB solo es necesaria en el nivel de instancia. Es decir, cada instancia particular de SLSB está sincronizada, pero puede tener varias instancias en un grupo o en un nodo diferente en un clúster, y las solicitudes simultáneas en instancias diferentes no son un problema.Desafortunadamente, esto no es tan fácil con SFSB debido a la pasivación/activación de instancias y la replicación en todo el clúster. Esta es la razón por la cual la especificación no hace cumplir esto. Eche un vistazo a this dicussion si está interesado en el tema.
Esto significa que el uso de SFSB del servlet es complicado. Un usuario con múltiples ventanas de la misma sesión o recarga de página antes de que finalice la renderización puede generar acceso concurrente. Cada acceso al EJB que se realiza en un servlet necesita teóricamente estar sincronizado en el mismo bean. Lo que hice fue crear un InvocationHandler para sincronizar todas las invocaciones en la instancia del EJB en particular:
public class SynchronizationHandler implements InvocationHandler {
private Object target; // the EJB
public SynchronizationHandler(Object bean)
{
target = bean;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
synchronized(target)
{
// invoke method to the target EJB
}
}
}
Entonces, justo después de obtener la referencia remota a la EJB, que se coloca con el SynchronizationHandler
. De esta forma, está seguro de que esta instancia particular no se accederá simultáneamente desde su aplicación (siempre que se ejecute en una sola JVM). También puede escribir una clase contenedora regular que sincronice todos los métodos del bean.
Mi conclusión es sin embargo: use SLSB siempre que sea posible.
EDITAR:
Esta respuesta refleja las especificaciones EJB 3.0 (sección 4.3.13):
Los clientes no se les permite hacer llamadas simultáneas a una sesión con estado objeto. Si un método comercial invocado por el cliente está en progreso en una instancia cuando otra llamada invocada por el cliente, del mismo o diferente cliente , llega a la misma instancia de una clase bean de sesión con estado, si el segundo cliente es un cliente de interfaz de negocio de la haba, la invocación concurrente puede resultar en el segundo cliente que recibe el javax.ejb.ConcurrentAccessException
Tales restricciones se han eliminado en EJB 3.1 (sección 4.3.13):
Por defecto, los clientes pueden hacer llamadas simultáneas a un objeto de sesión stateful y el contenedor es necesario para serializar dichas solicitudes simultáneas .
[...]
The Bean desarrollador puede especificar opcionalmente que el cliente concurrentes están prohibidas peticiones a un bean de sesión con estado. Esto se hace usando el elemento del descriptor de despliegue an12Ade anotación de acceso o tiempo de espera @AccessTimeout con un valor de 0. En este caso, si un método de negocio invocado por cliente está en progreso en una instancia cuando otra llamada invocada por el cliente el mismo o diferente cliente, llega a la misma instancia de un bean de sesión con estado , si el segundo cliente es un cliente de la interfaz comercial del bean o vista sin interfaz, la invocación simultánea debe dar como resultado que el segundo cliente reciba un javax.ejb.ConcurrentAccessException
AFAIK, Al crear un origen de datos en un servidor de aplicaciones, debe saber de antemano que existe la base de datos. La conexión anterior se realiza en una base de datos a la que un usuario especificó debemos conectarnos. – Burmudar
Esto me parece terriblemente inseguro. – duffymo