Subprocesos del servidor de aplicaciones y JPA / Hibernate Optimistic Locking - OptimisticLockException

Tengo una aplicación Spring MVC ejecutándose en el servidor de aplicaciones. Cada solicitud a la aplicación hace que Hibernate llame a la entityManager.merge () para actualizar una fila en la base de datos.

Realicé una prueba hoy enviando múltiples solicitudes y noté que algo me sale el siguiente error:

javax.persistence.OptimisticLockException
        at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:340) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:214) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:190) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:540) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50) [resteasy-jaxrs-2.3.1.GA.jar:]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]
        at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.0.Final.jar:7.1.0.Final]
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]
        at java.lang.Thread.run(Thread.java:619) [rt.jar:1.6.0_20]

Para poder resolver lo anterior necesito entender lo siguiente:

  • ¿Cómo se manejan las solicitudes en el servidor de aplicaciones? ¿Es el caso que cada solicitud es procesada por su propio hilo?

  • Al observar el error, noté que se los denominaba (http - 10.10.4.16-8080-1) y (http - 10.10.4.16-8080-7). ¿Es el número al final el número de subproceso que procesó la solicitud?

  • OptimistiLockException sugiere que hubo un intento de actualizar el mismo mensaje antes de que JPA / Hibernate emitiera una confirmación. Si pongo el código relevante en un bloque sincronizado, ¿cómo me aseguro de que el orden en que llegaron las solicitudes es el orden en que se procesan cuando el bloque sincronizado está disponible?

  • ¿Hay alguna manera de indicarle a JPA / Hibernate que no intente actualizar el mensaje si hay cambios no confirmados?

Gracias

Respuesta 1

Las soluciones disponibles para usted dependen de cómo haya diseñado sus niveles y de dónde proviene la entidad que está fusionando. ¿La entidad separada está siendo ensamblada por la carpeta de datos de Spring, o almacenada en la sesión web, o está buscando una entidad de la base de datos y haciéndole cambios en el momento en que llega la solicitud?

¿Cómo se manejan las solicitudes en el servidor de aplicaciones? ¿Es el caso que cada solicitud es procesada por su propio hilo?

Son manejados por un grupo de subprocesos. Por lo tanto, cada solicitud no obtiene "su propio" subproceso, pero en un momento dado cada solicitud activa está siendo procesada por un subproceso seoarate, sí. (O en una cola esperando que uno se libere).

Al observar el error, noté que se los denominaba (http - 10.10.4.16-8080-1) y (http - 10.10.4.16-8080-7). ¿Es el número al final el número de subproceso que procesó la solicitud?

Todo es el nombre del hilo. Tomcat pone números al final para hacerlos únicos, pero ese # no tiene ningún significado particular que no sea una cadena secuencial arbitraria asignada por tomcat.

OptimistiLockException sugiere que hubo un intento de actualizar el mismo mensaje antes de que JPA / Hibernate emitiera una confirmación. Si pongo el código relevante en un bloque sincronizado, ¿cómo me aseguro de que el orden en que llegaron las solicitudes es el orden en que se procesan cuando el bloque sincronizado está disponible?

Si el pedido es importante, deberá colocarlos en algún tipo de cola antes de procesarlos. La sincronización no hace promesas sobre el orden de ejecución de subprocesos en espera. Si este proceso no debe fallar, considere usar un bloqueo pesimista en la base de datos en lugar de sincronizarlo en el servidor de aplicaciones. Es posible que algún otro subproceso que use la tabla no moleste en sincronizar y cause la excepción de todos modos.

¿Hay alguna manera de indicarle a JPA / Hibernate que no intente actualizar el mensaje si hay cambios no confirmados?

En realidad no, no hay ninguna forma directa de verificar si una entidad tiene actualizaciones pendientes en alguna otra sesión en la memoria caché. La verificación OptimisticLock es el mecanismo para saber si alguien más realizó un cambio.

Respuesta: 2

Tengo: List <Object []> Me gustaría convertir a: List <MyClass> Obviamente, es posible iterar toda la lista, pero ¿puede existir una clase lista para ello? Gracias.

Estoy desarrollando una aplicación Java independiente que recopila datos de alrededor de 1000 dispositivos de medición a través de la red y los mantiene en una base de datos. La recopilación de datos puede tomar un par de ...

Quiero tener una clase de búsqueda con varias opciones diferentes, mi clase de búsqueda debería poder filtrar los resultados de diferentes maneras, tales como: getX () getY () getZ () getK () por encima de X, Y, Z, K son mi ...

Tengo un edificio de aplicaciones web de módulos múltiples con maven. Construimos la guerra como de costumbre y la implementamos y ejecutamos en máquinas de desarrollo y servidores de prueba locales utilizando Tomcat. Entonces queremos implementar la aplicación ...