2012-04-10 14 views
10

Se ha informado de las pruebas de que a veces es posible presionar un botón más de una vez si la respuesta no se procesa lo suficientemente rápido, lo que provoca varias invocaciones del código de fondo, que no queremos.¿Cómo manejar múltiples envíos antes de que se muestre la respuesta?

La aplicación es Java EE 6 Web Profile utilizando JSF 2.0 dentro de Glassfish 3.1.1.

me preguntaba cómo este debe ser adecuadamente tratados, y han pensado en una serie de escenarios:

  • entrega debería deshabilitar todos los botones usando Javascript mientras que la respuesta se está representando.
  • Un indicador en el ámbito de la sesión que dice que ya está activo, por lo que el código confidencial se salta y pasa a la representación de la respuesta para el envío anterior.
  • Un bloque sincronizado que retrasa el procesamiento hasta que finaliza la solicitud anterior. Luego debe detectarse que ya se ha procesado y omitido.
  • ¿Utiliza uno de los "nuevos" ámbitos como la conversión para manejar la detección?

Mi intuición inmediata es que el mejor enfoque es tener bloques de código sensibles atómicos, pero entonces el problema es dar la respuesta correcta.

¿Cómo debo abordar esto?

+0

¿Has probado algo como jQuery blockui? Por cierto, el bloque sincronizado no funcionará en un clúster. –

+0

No se ha intentado nada todavía. Esto está en el "bien, ¿cómo hago eso?" escenario. –

Respuesta

2

Como mencionó Adrian, también usaría BlockUI. Hay un BlockUI component de Primefaces. Cuando envía sus formularios a través de ajax, también puede usar una superposición durante la solicitud. Consulte Primefaces`s Ajax Status para ver un ejemplo.

10

La presentación debe deshabilitar todos los botones mediante javascript mientras se está respondiendo.

Este es el más fácil de implementar de forma genérica. Si usa <f:ajax> exclusivamente, puede usar jsf.ajax.addOnEvent() para realizar el trabajo de manera genérica. Un enfoque alternativo de JavaScript es crear una especie de superposición de "Carga" que bloquea la interfaz de usuario para que el usuario final ya no pueda interactuar con la página subyacente. Esto es básicamente un <div> oculto absolutamente posicionado que abarca toda la ventana gráfica con algo de opacity (transparencia). Puede mostrarlo en el envío y ocultarlo en el procesamiento. La palabra clave para esta técnica es "modal dialog". Las bibliotecas de componentes JSF orientadas a la interfaz de usuario ya tienen al menos un componente de este tipo en su surtido. P.ej. PrimeFaces con un <p:dialog modal="true"> dentro de un <p:ajaxStatus>, o la <p:blockUI>

La única desventaja es que no va a funcionar si el cliente tiene JS desactivado o no usarlo y que por lo tanto no va a evitar que los clientes HTTP desde somete dobles.


Una bandera en el ámbito de la sesión diciendo que ya está activo, por lo que el código sensibles se omite y sólo se mueve a la re-representación de la respuesta a la anterior someterse.

Esto es más conocido como "synchronizer token pattern" de los siglos se ha solicitado para JSF por spec issue 559 que actualmente se encuentra en el boleto blanco de 2,2, pero no parece haber ninguna actividad en ella. La parte de detección y bloqueo es técnicamente fácil de implementar, pero la parte de manejo de respuesta síncrona no es fácil de implementar si se desea que el usuario final recupere finalmente la respuesta generada por la solicitud inicial. El manejo de respuesta asíncrona es fácil: simplemente no especifique ningún componente para actualizar, es decir, vacíe la colección devuelta por PartialViewContext#getRenderIds(). Después de todo, esto es más sólido que usar JS para desactivar los botones o bloquear la IU. Por lo que sé, Seam 2 fue el único que ofreció un componente JSF reutilizable para esto, el <s:token>. Sin embargo, debo admitir que esta es una idea interesante para un nuevo componente OmniFaces. Tal vez personalmente lo echaré un vistazo.


Un bloque sincronizado retrasar el procesamiento hasta que la solicitud anterior haya terminado. Luego debe detectarse que ya se ha procesado y omitido.

Esto no es fácil de implementar genéricamente, esto requeriría un cambio en todos los métodos de acción para verificar si el trabajo ya está hecho. Tampoco funcionará si la aplicación web se ejecuta en varios servidores. Un token de sincronizador es más fácil ya que se realizaría antes de invocar los métodos de acción. Un token de sincronizador también es menos costoso, ya que no se generan múltiples solicitudes en la cola, que solo costarían hilos/recursos.


Utilizando uno de los "nuevos" ámbitos como la conversión de manejar la detección?

Este problema no se puede resolver jugando con ámbitos administrados de beans. Los alcances administrados de beans tienen un propósito diferente: el tiempo de vida de la instancia de beans.

+0

Además del "bloque sincronizado", también puede consultar este filtro: http://onjava.com/onjava/2004/03/24/examples/RequestControlFilter.java –

+0

Gracias por una respuesta muy informativa. ¿Tienes sugerencias adicionales que no pensé en mí mismo? –

+0

De nada. No, en realidad no hay otras maneras de usar JS para deshabilitar/bloquear la interacción del usuario, o usar el patrón de token del sincronizador. – BalusC

Cuestiones relacionadas