2012-04-10 2 views
10

È stato segnalato dal test che è talvolta possibile premere un pulsante più di una volta se la risposta non è resa abbastanza veloce, causando diverse invocazioni del codice di back-end, che non vogliamo.Come gestire più segnalazioni prima che la risposta sia resa?

L'applicazione è Java EE 6 profilo Web che utilizza JSF 2.0 all'interno di Glassfish 3.1.1.

mi chiedevo come questo dovrebbe essere correttamente trattati, e hanno pensato di alcuni scenari:

  • Sottoporre dovrebbe disattivare tutti i pulsanti che utilizzano JavaScript mentre la risposta viene reso.
  • Un flag nello scenario Session che dice che è già attivo, quindi il codice sensibile viene saltato e passa al re-rendering della risposta per l'invio precedente.
  • Un blocco sincronizzato che ritarda l'elaborazione fino al completamento della richiesta precedente. Quindi dovrebbe essere rilevato che è già stato elaborato e saltato.
  • Utilizzando uno dei "nuovi" ambiti come la conversione per gestire il rilevamento?

La mia sensazione istintiva immediata è che l'approccio migliore è quello di avere blocchi di codice sensibili atomici, ma il problema è con il rendering della risposta corretta.

Come devo affrontare questo?

+0

Hai provato qualcosa come jQuery blockui? Il blocco sincronizzato BTW non funzionerà su un cluster. –

+0

Non è stato ancora provato nulla. Questo è al "bene, come faccio?" palcoscenico. –

risposta

2

Come accennato da Adrian, utilizzerei anche BlockUI. C'è un BlockUI component da Primefaces. Quando invii i moduli tramite ajax, puoi anche utilizzare una sovrapposizione durante la richiesta. Vedi Primefaces`s Ajax Status per un esempio.

10

L'invio deve disabilitare tutti i pulsanti utilizzando javascript mentre la risposta è in fase di rendering.

Questo è il più semplice da implementare in modo generico. Se si utilizza esclusivamente <f:ajax>, è possibile utilizzare lo jsf.ajax.addOnEvent() per eseguire il lavoro in modo generico. Un approccio JavaScript alternativo consiste nel creare una sorta di sovrapposizione "Caricamento" che blocca l'interfaccia utente in modo che l'utente finale non sia più in grado di interagire con la pagina sottostante. Questo è fondamentalmente un <div> nascosto in modo assoluto che copre l'intera finestra con qualche opacity (trasparenza). Puoi mostrarlo su submit e nasconderlo sul render. La parola chiave per questa tecnica è "modal dialog". Le librerie di componenti JSF orientate all'IU hanno già almeno un componente del genere nel loro assortimento. Per esempio. PrimeFaces con un <p:dialog modal="true"> all'interno di un <p:ajaxStatus>, oppure il <p:blockUI>

L'unico svantaggio è che non funziona se il cliente ha JS disabilitato o non lo usate e quindi non impedirà client HTTP da doppie sottomette.


Una bandiera nel campo di applicazione della sessione dicendo che è già attivo, in modo sensibile il codice viene saltata e l'appena si muove al ri-rendering della risposta per il precedente invio.

Questo è più conosciuta come "synchronizer token pattern" ed è stato mai richiesto per JSF da spec issue 559 che è attualmente sul biglietto mirato per 2.2, ma non sembra essere qualsiasi attività su di esso. La parte di rilevamento e blocco è tecnicamente facile da implementare, ma la parte di gestione della risposta sincrona non è facile da implementare se si desidera che l'utente finale recuperi in definitiva la risposta come generata dalla richiesta iniziale. La gestione della risposta asincrona è semplice: non specificare alcun componente da aggiornare, ovvero svuotare la raccolta restituita da PartialViewContext#getRenderIds(). Dopo tutto, questo è più robusto dell'utilizzo di JS per disabilitare i pulsanti o bloccare l'interfaccia utente.

Per quanto ne so, Seam 2 è stato l'unico a offrire un componente JSF riutilizzabile per questo, lo <s:token>. Devo comunque ammettere che questa è un'idea interessante per un nuovo componente OmniFaces. Forse lo guarderò personalmente.


Un blocco sincronizzato ritardare l'elaborazione finché la richiesta precedente hanno terminato. Quindi dovrebbe essere rilevato che è già stato elaborato e saltato.

Questo non è facile da implementare genericamente, ciò richiederebbe un cambiamento in tutti i metodi di azione per verificare se il lavoro è già fatto. Inoltre, non funzionerà se l'applicazione web viene eseguita su più server. Un token di sincronizzazione è più semplice in quanto verrebbe eseguito prima che i metodi di azione venissero richiamati. Un token di sincronizzazione è anche meno costoso in quanto non si ottengono più richieste in coda che costano solo thread/risorse.


Utilizzando uno dei "nuovi" ambiti come la conversione di gestire la rilevazione?

Questo problema non può essere risolto giocando con gli ambiti dei bean gestiti. Gli ambiti bean gestiti hanno uno scopo diverso: la durata dell'istanza del bean.

+0

Come aggiunta a "blocco sincronizzato" si può anche guardare questo filtro - http://onjava.com/onjava/2004/03/24/examples/RequestControlFilter.java –

+0

Grazie per una risposta molto informativa. Hai altri suggerimenti che non pensavo di me stesso? –

+0

Prego. No, non ci sono altri modi per utilizzare JS per disabilitare/bloccare l'interazione dell'utente o utilizzare il modello di token del sincronizzatore. – BalusC