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