2015-11-17 32 views
7

Sto cercando di raggiungere i seguenti obiettivi:EJB @Asynchronous per recuperare in tempo reale inserito fila in JSF sembra essere Discussione chiusa

EJB3 Singleton

@Singleton 
@Startup 
public class SomeSingleton implements SomeSingletonLocal { 

    // Entity Manager injection 
    private EntityManager _entity_manager; 

    @Override 
    @Asynchronous 
    public void createScenario(){ 
     method1(); 
     method2(); 
     // ... 
    } 

    public void method1(){ 
     // Persist an Event in a Database. 
    } 

    public void method2(){ 
     // Persist an Event in a Database. 
    } 

} 

Managed Bean

@ManagedBean 
@RequestScoped 
public class SomeManagedBean{ 

    // Entity Manager injection 
    private EntityManager _entity_manager; 

    @EJB 
    private SomeSingletonRemote _singleton; 

    public void createScenario(){ 
     _singleton.createScenario(); 
    } 

    public List<Event> getEventList(){ 
     // Retrieve events from database 
    } 
} 

JSF view

<h:form> 
    <p:commandButton value="Start Long Stuff" 
     actionListener="#{SomeManagedBean.createScenario}" /> 
    <h:outputText id="count" value="#{SomeManagedBean.getEventList.size()}" /> 
      <p:poll interval="1" update="count" /> 
</h:form> 

registro

-> SomeManagedBean.getEventList()
< -SomeManagedBean.getEventList() // Size = 0

// Buton cliccato
-> SomeManagedBean .createScenario()
            -> SomeSingleton.createScenario()
< -SomeManagedBean.createScenario()

-> SomeManagedBean.getEventList() // si concluderà alla fine del SomeSingleton.createScenario
-> SomeSingleton.method1()
< -SomeSingleton.method1() // persistono
...
-> SomeSingleton.methodN()
< -SomeSingleton.methodN() // persistere

< -SomeSingleton.createScenario()

< -SomeManagedBean.getEventList() // size = N

I prevede almeno una chiamata al getEventList tra due methodI() chiamata (es. ogni secondo). Quando entra in SomeSingleton.createScenario(), non so perché getEventList è in pausa.

Sembra che ci sia un blocco con il gestore entità o la transazione all'interno di createScenario. È un problema di reentrance?

risposta

8

A @Singleton è in realtà l'impostazione predefinita di lettura/scrittura bloccata. Questo non è strettamente correlato alle transazioni, ma alla concorrenza. Vedi anche a.o. Java EE 7 tutorial on the subject.

Un modo per risolverlo è impostare @ConcurrencyManagement su BEAN. In questo modo, in pratica, dici al contenitore di non preoccuparti affatto della concorrenza e di assumerti tutte le responsabilità da solo.

@Singleton 
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) 
public class SomeSingleton {} 

Un altro modo è quello di definire esplicitamente @Lock per READ sulla classe o metodi di sola lettura in modo che possano essere contemporaneamente invocati.Solo quando viene invocato un metodo con un @Lock(LockType.WRITE) esplicito sulla stessa istanza, si verificherà il blocco.

@Singleton 
@Lock(LockType.READ) 
public class SomeSingleton {} 
+0

Perché hanno [menzione] (https://docs.oracle.com/javaee/7/tutorial/ejb-basicexamples002.htm), "* Se non' @ Lock' annotazione è presente sul Singleton classe, il tipo di blocco predefinito, '@Lock (LockType.WRITE)', viene applicato a tutti i metodi business e timeout * "? – Tiny

+0

@Tiny: puoi chiarire quale parte esattamente non è chiara per te? In pratica dice che quando non ci sono annotazioni '@ Lock' sulla classe, tutti i metodi sono predefiniti in' @Lock (LockType.WRITE) '. Questo è anche coperto dalla risposta (ma forse in un modo un po 'confuso e mi piacerebbe migliorare quella parte quindi, a seconda del tuo feedback). – BalusC

+0

Queste lettere in grassetto qui: "* A' @ Singleton' è infatti di default ** read/write locked *** ". (Scusa, inizialmente ho avuto un'impressione errata, un EJB singleton ha sia "read" che "write" come default, in questo modo, i metodi che cambiano gli stati dovrebbero essere "write" bloccati di default e il resto, se ce n'è uno, che fa non cambiare stato dovrebbe essere "letto" bloccato di default). – Tiny