2016-01-26 46 views
5

Sto utilizzando Mojarra 2.2.12 e nel nostro progetto abbiamo alcuni fagioli @ApplicationScoped. Ad esempio:Concorrenza di @ApplicationScoped Fagioli gestiti JSF

@ManagedBean 
@ApplicationScoped 
public class AppScopedBean{ 

    private int commonValueForClients; 

    //GET, SET 

    public void evalNew(){ 
     int newCommonVal; 
     //Evaluation of the new value, doesn't depend on the commonValueForClients 
     commonValueForClients = newCommonVal; 
    } 
} 

La mia domanda è: dovremmo preoccuparci della visibilità del nuovo valore assegnato?

Non è stato possibile trovare in the spec che l'infrastruttura JSF deve sincronizzare l'accesso ai campi del bean @ApplicationScoped. Quindi, in particolare per Mojarra 2.2.12, dovremmo dichiarare il campo come volatile o sincronizzarlo in modo esplicito?

+0

Dal mio punto di vista, si è scelto un ambito di bean errato. Il dolore severo e la sofferenza saranno le conseguenze della mancata scelta del giusto ambito di un particolare fagiolo gestito. – Tiny

+0

@Tiny Forse, il caching non è strettamente adatto per i fagioli gestiti, credo. È piuttosto uno scopo di servizio. –

risposta

8

JSF fa non sincronizzare qualsiasi accesso ai bean gestiti in qualsiasi ambito.

Questa è la tua responsabilità. Utilizzare i wrapper di concorrenza/sincronizzazione esistenti come tipi di campo come AtomicInteger, ConcurrentHashMap, Collections#synchronizedList(), ecc. Utilizzare volatile solo come ultima risorsa se non esiste alcun wrapper di questo tipo.

La sincronizzazione di oggetti mutabili è sicuramente necessaria nei bean con ambito applicazione. In caso di es. HashMap, si rischia altrimenti di rischiare anche un stuck thread (100% CPU). È meno strettamente necessario nei bean con scope di sessione poiché verranno acceduti contemporaneamente quando l'utente finale apre più connessioni HTTP nella stessa sessione, e questo sarà by default solo quando vengono generate due istanze del browser fisicamente diverse, ma a turno verranno impostate per impostazione predefinita già non condividere la sessione. Quindi accadrebbe solo in caso di robot/hacker ed è quindi fortemente raccomandato di occuparsene anche nei bean con scope di sessione. È quasi inutile in vista dei bean con scope dato che le richieste ajax sono by specification accodate, ma in PrimeFaces può essere disattivato da <p:ajax async="true">, e dovresti tenerne conto anche nel bean con scope vista. È totalmente inutile nei bean con scope richiesta.

Se si dispone di CDI con le mani, è anche possibile simulare l'annotazione di EJB @Lock con un'annotazione personalizzata e un intercettore CDI. Questo è dettagliato nel blog di Stephan Kintelius: Concurrency control for CDI, pubblicato casualmente il giorno prima della tua domanda. Tieni presente che la funzione di gestione dei bean JSF è scartata a JSF 2.3 a favore di CDI. Vedere anche Backing beans (@ManagedBean) or CDI Beans (@Named)? Se possibile, passare a CDI per la gestione dei bean.

+0

Interessante, ma le specifiche non sono chiare. È possibile per l'implementazione sincronizzarlo ...? Voglio dire, per evitare la sovrascrittura e usare alcune caratteristiche impl-specific per l'amor di prestazione. –

+0

_Usa volatile solo come ultima risorsa se non esiste un tale involucro. _ Perché la pensi così? Ho pensato che il campo volatile combinato con oggetti immutabili sia una tecnica innovativa per la sicurezza del filo. –

+0

L'implementazione potrebbe davvero scegliere di farlo, ma sarebbe semplicemente inefficiente in quanto la sincronizzazione non è sempre necessaria. La necessità dipende dal design della classe bean e questo è invisibile dall'implementazione in poi. Per quanto riguarda "volatile", questi involucri non sono immutabili. – BalusC