EJB @Asynchronous для извлечения вставленной в реальном времени строки в JSF, похоже, заблокирован потоком

Я пытаюсь добиться следующего:

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

}

Управляемый 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

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

журнал

- > SomeManagedBean.getEventList()
< -SomeManagedBean.getEventList()//Размер = 0

//Бутон нажал
- > SomeManagedBean.createScenario()
      → SomeSingleton.createScenario()
< -SomeManagedBean.createScenario()

- > SomeManagedBean.getEventList()//закончится в конце SomeSingleton.createScenario
- > SomeSingleton.method1()
< -SomeSingleton.method1()//persist
 ...
- > SomeSingleton.methodN()
< -SomeSingleton.methodN()//persist

< -SomeSingleton.createScenario()

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

Я ожидал хотя бы одного вызова getEventList между двумя вызовами methodI() (т.е. каждую секунду). Когда он входит в SomeSingleton.createScenario(), я не знаю, почему getEventList приостановлен.

Похоже, есть блокировка с менеджером сущности или транзакцией внутри createScenario. Это проблема повторного входа?

Ответы

Ответ 1

A @Singleton действительно по умолчанию используется для чтения/записи. Это не связано исключительно с транзакциями, но с concurrency. См. Также a.o. Учебник по Java EE 7 по теме.

Один из способов решения этой проблемы - установить @ConcurrencyManagement на BEAN. Таким образом, вы в основном говорите контейнеру, чтобы не беспокоиться о concurrency вообще и что вы берете на себя всю ответственность.

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

Другой способ - явно указать @Lock на READ класс или прочитать - только методы, с помощью которых они могут одновременно вызываться. Только когда метод с явным @Lock(LockType.WRITE) вызывается в том же экземпляре, тогда произойдет блокировка.

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