Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EJB @Asynchronous to retrieve real time inserted row in JSF seems to be thread locked

I am trying to achieve the following :

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>

log

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

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

->SomeManagedBean.getEventList() // will end at the end of SomeSingleton.createScenario
->SomeSingleton.method1()
<-SomeSingleton.method1() // persist
...
->SomeSingleton.methodN()
<-SomeSingleton.methodN() // persist

<-SomeSingleton.createScenario()

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

I expected at least one call to getEventList between two methodI() call (ie. each second). When it enters in SomeSingleton.createScenario(), I dont know why getEventList is paused.

It looks like there is a lock with the entity manager or the transaction inside createScenario. Is that a reentrance problem ?

like image 423
Charles Follet Avatar asked Nov 17 '15 10:11

Charles Follet


1 Answers

A @Singleton is indeed by default read/write locked. This is not strictly related to transactions, but to concurrency. See also a.o. Java EE 7 tutorial on the subject.

One way to solve it is to set the @ConcurrencyManagement to BEAN. This way you basically tell the container to not worry about concurrency at all and that you take all responsibility on your own.

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

Another way is to explicitly set @Lock to READ on the class or the read-only methods so that they can concurrently be invoked. Only when a method with an explicit @Lock(LockType.WRITE) is invoked on the same instance, then the lock will occur.

@Singleton
@Lock(LockType.READ)
public class SomeSingleton {}
like image 153
BalusC Avatar answered Nov 15 '22 04:11

BalusC