2015-11-17 2 views
7

Ich versuche, um folgendes zu erreichen:EJB @Asynchronous Echtzeit abgerufen werden eingefügten Zeile in JSF scheint Thread zu sein gesperrt

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 Ansicht

<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> 

log

-> SomeManagedBean.getEventList()
< -SomeManagedBean.getEventList() // Größe = 0

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

-> SomeManagedBean.getEventList() // wird am Ende des SomeSingleton.createScenario Ende
-> SomeSingleton.method1()
< -SomeSingleton.method1() //
bestehen ...
-> SomeSingleton.methodN()
< -SomeSingleton.methodN() // bestehen

< -SomeSingleton.createScenario()

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

I mindestens einen Anruf zu geteventlist erwartet zwischen zwei Methodi() Aufruf (dh. jede Sekunde). Wenn es in SomeSingleton.createScenario() eintritt, weiß ich nicht, warum getEventList pausiert ist.

Offenbar gibt es eine Sperre mit dem Entity Manager oder der Transaktion innerhalb createScenario. Ist das ein Wiedereintrittsproblem?

Antwort

8

Ein @Singleton ist zwar standardmäßig schreibgeschützt. Dies bezieht sich nicht ausschließlich auf Transaktionen, sondern auf Nebenläufigkeit. Siehe auch a.o. Java EE 7 tutorial on the subject.

Eine Möglichkeit, es zu lösen, ist die @ConcurrencyManagement auf BEAN zu setzen. Auf diese Weise teilen Sie dem Container grundsätzlich mit, dass er sich nicht um Nebenläufigkeit kümmern soll und dass Sie selbst alle Verantwortung übernehmen.

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

Eine andere Möglichkeit ist ausdrücklich @Lock-READ auf die Klasse zu setzen oder den Nur-Lese-Methoden, so dass sie gleichzeitig aufgerufen werden können.Erst wenn ein Verfahren mit einer expliziten @Lock(LockType.WRITE) auf derselben Instanz aufgerufen wird, dann wird die Sperre auftreten.

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

Warum haben sie [Erwähnung] (https://docs.oracle.com/javaee/7/tutorial/ejb-basicexamples002.htm) „, * Wenn kein' @ Lock' Anmerkung ist auf dem Singleton class, wird der Standardsperrtyp "@Lock (LockType.WRITE)" auf alle Geschäfts- und Timeout-Methoden angewendet * "? – Tiny

+0

@Tiny: Kannst du bitte klarstellen, welcher Teil genau für dich unklar ist? Es sagt im Grunde, dass wenn es keine '@ Lock' Anmerkung auf der Klasse, dann werden alle Methoden standardmäßig' @Lock (LockType.WRITE) '. Dies wird auch durch die Antwort abgedeckt (aber vielleicht auf eine etwas unklare Art und ich möchte diesen Teil dann verbessern, abhängig von Ihrem Feedback). – BalusC

+0

Diese fetten Buchstaben hier: „* A' @ Singleton' zwar standardmäßig ** Lese-/Schreib gesperrt ***“. (Sorry, ich habe zunächst einen falschen Eindruck, ein Singleton EJB hat sowohl „Lesen“ und „Schreiben“ Sperren als Standard vielleicht diese Weise Methoden Zustände zu ändern sollten „schreiben“ gesperrt standardmäßig aktiviert und den Rest, wenn überhaupt, was zu tun Status nicht ändern sollte "gelesen" standardmäßig gesperrt sein. – Tiny