EJB @Asynchronous для извлечения вставленной в реальном времени строки в JSF, кажется, заблокирован потоком
Я пытаюсь добиться следующего:
EJB3 Синглтон
@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.
}
}
Управляемый Боб
@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>
журнал
-> SomeManagedBean.getEventList ()
<-SomeManagedBean.getEventList () // Size = 0// Бутон нажал
-> SomeManagedBean.createScenario ()
-> SomeSingleton.createScenario ()
<-SomeManagedBean.createScenario ()->SomeManagedBean.getEventList() // закончится в конце SomeSingleton.createScenario
-> SomeSingleton.method1 ()
<-SomeSingleton.method1 () // сохраняться
...
-> SomeSingleton.methodN ()
<-SomeSingleton.methodN () // сохраняться<-SomeSingleton.createScenario ()
<-SomeManagedBean.getEventList () // size = N
Я ожидал по крайней мере один вызов getEventList между двумя вызовами methodI() (т.е. каждую секунду). Когда он входит в SomeSingleton.createScenario(), я не знаю, почему getEventList приостановлен.
Похоже, что есть блокировка с менеджером сущностей или транзакцией внутри createScenario. Это проблема реентера?
1 ответ
@Singleton
действительно по умолчанию чтение / запись заблокированы. Это не строго связано с транзакциями, но с параллелизмом. См. Также учебник по Java EE 7 по этому вопросу.
Один из способов решить эту проблему - установить @ConcurrencyManagement
в BEAN
, Таким образом, вы в основном указываете контейнеру вообще не беспокоиться о параллелизме и что вы берете на себя всю ответственность самостоятельно.
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class SomeSingleton {}
Другой способ состоит в том, чтобы явно установить @Lock
в READ
в классе или только для чтения, так что они могут быть вызваны одновременно. Только когда метод с явным @Lock(LockType.WRITE)
вызывается в том же экземпляре, затем происходит блокировка.
@Singleton
@Lock(LockType.READ)
public class SomeSingleton {}