Control de Doble Click en JSP y Struts
Cuando realizamos una aplicación Web, hay un problema bastante común y se
produce cuando el usuario realiza una transacción:
- Hace un doble click muy rápido sobre un botón invocando doblemente
transacciones - Se pone nervioso y, antes de que termine, la vuelve a invocar.
- Se produce un error y no está seguro de que las transacciones se hayan
confirmado por lo que lo reintenta para ver que le dice el sistema.. - Pulsa el botón volver, refrescar y avanzar con lo que reenvía una misma
transacción dos veces.
Una de las soluciones, que habitualmente se utiliza, es escribir un pequeño
código JavaScript que nos permita evitar la situación (al menos parcialmente).
El primer problema de esta aproximación es conceptual: Jamás me debo fiar de
las validaciones realizadas en el cliente Web (aparte de la parcialidad de la
solución) porque:
- Son fácilmente evitables.
- JavaScript depende de la versión del navegador (y sistema operativo) que
complica la mantenibilidad. - JavaScript puede desactivarse.
- Podemos hacer un programas que automatice una petición HTTP sin que exista
un navegador (y empezad a pensar en WebServices)
Las validaciones importantes hay que controlarlas siempre en el servidor
(aunque las complementemos en el cliente para evitar flujos innecesarios de
información).
Tenemos que entender los posibles estados que podemos tener el problema:
- Un usuario llega a un punto que donde se autoriza una nueva transacción
(se activa un ticket o token) - El usuario ejecuta una vez esa transacción y se deshabilita el token
- El usuario para poder ejecutar esa misma transacción de nuevo tiene que
llegar a un punto que le vuelva a habilitar el token
El párrafo anterior está escrito en un lenguaje poco técnico lo
que provoca ambigüedades . Podríamos tratar de utilizar UML para concretar un
poquito más los posibles estados y tratar de plasmar en el futuro las posibles
variaciones.
Este problema lo podríamos tener tanto en una aplicación con interfaz tipo
Windows o en una aplicación Web ….. Lo lógico sería tratar de construir una
librería que pudiera se invocada por distintos tipos de aplicaciones.
Nosotros no vamos a ir tan allá pero trataremos de dar el primer paso en la
solución creando unas librerías de etiquetas básicas para resolverlo en
aplicaciones Web/JSP.
Construiremos un pequeño ejemplo que veremos elemento a elemento.
El formulario
Partimos de un formulario donde mandaremos al servidor un campo oculto. En
este campo se almacena un valor que solo es utilizable una vez. El encargado de
generar y validar este parámetro es siempre el servidor y lo hacemos a través de
una etiqueta. Pasamos como parámetro el nombre de la transacción (ejemplo)
para poder tener tantos tokens activos como deseemos.
<controltokens:generaToken nombreTransaccion=»ejemplo«/>
Podemos ver el aspecto de la página
Y el código que llegaría a nuestro navegador. Hemos elegido como
token la fecha actual pero podría ser cualquier cosa
La rutina transaccional
Cuando ejecutemos la transacción debemos verificar que el toquen es válido.
Usamos otro JSP.
<controltokens:compruebaToken nombreTransaccion=»ejemplo«/>
Si no es así, generamos una excepción y redirigimos a una página de error
errorPage=»/pages/transaccionDuplicada.jsp«
Si la ejecutamos una vez
Si ejecutamos la segunda vez (con refrescar, volver y enviar,
volver-refrescar y enviar).
Limpiar el token
En el caso de querer volver a ejecutar la transacción deberíamos
pasar por una página que rehabilitase el token.
<controltokens:anulaToken nombreTransaccion=»ejemplo«/>
Librería de TAGS
Ahora solo tenemos que revisar el tutorial donde
os mostrábamos como crear
paso a paso una etiqueta y analizar el código particular.
El tag de generación de token
El tag de Verificación/desactivación
El tag de reactivación
No olvidar modificar el fichero web.xml para poder utilizar las tags
en nuestras páginas JSP
Como habréis podido observar el efecto es el deseado aunque todavía quedarían
por dar muchos pasos:
- Deberíamos construir un juego de pruebas detallado que nos garantizase su
correcto comportamiento. - Como segundo paso deberíamos sacar del código de las TAGs a librerías más
genéricas para utilizarlas en aplicaciones tipo MVC y otro tipo de interfaces. - Como tercer paso, deberíamos ligar estas capacidades dentro de nuestro
FrameWorks para que incluso se generase automáticamente el código redundante
en el cliente - Y aún podríamos hacer más cosas….
Control de transacciones y Struts
Mucha gente utiliza Struts pensando que el control de transacciones y doble
clicks ya esta solucionado…. pero no es así de automático.
En la acción que deseamos que active el control transaccional (previo al
formulario) debemos llamar a la función:
saveToken(httpServletRequest);
Los formularios tenemos que montarlos con la etiqueta de Struts html
Podemos ver que pasa algo similar a lo que hicimos con nuestras tags
Posteriormente en la acción que ejecuta la transacción podemos verificar el
token e invalidarlo con:
if( this.isTokenValid(httpServletRequest)==true)
Y luego limpiarlo con
this.resetToken(httpServletRequest);
Conclusiones
El desarrollo de aplicaciones Web es un arte bastante compleja aunque
aparentemente pudiera parecer lo contrario Uno de los problemas es que la
misma cosa se puede hacer de muchos modos y es fácil que elijamos uno poco
afortunado.
Este ejemplo no soluciona todos los problemas pero sienta unas bases para el
estudio y solución del mismo..
Si estudiáis metodologías tipo Programación Extrema, observareis que uno de
los principios a tener en cuenta es realizar diseños sencillos. Esto significa
(y es una posible interpretación personal) que no debemos diseñar una solución
pensando en los problemas que tendremos dentro de dos años sino los que
tendremos dentro de dos meses… Dentro de dos años ya veremos….