Взаимодействие с EJB (и EntityManager) от одноэлементных демонов, MDB и веб-контроллеров в одном ухе

Есть стек технологий: Java EE (WebSpere), JPA, EJB3, JMS (MDB), JSF.

Архитектура: сообщения JMS поступают (через MDB) и регистрируются как постоянные сущности (с помощью EntityManager). Существует класс Singleton с бесконечным циклом, который отвечает за обработку этих сущностей. Singleton уведомляется о созданных сущностях MDB. Изначально сущности хранятся в очереди внутри синглтона. Созданный объект может обрабатываться до нескольких минут. Одновременно может обрабатываться не более определенного количества сущностей (несколько параллельных процессов в Singleton). Синглтон не является EJB, но он использует службы EJB. Существует класс, который представляет контекст выполнения для данного объекта (простой DTO). Контекст выполнения содержит зависимости от необходимых EJB и создается на этапе взаимодействия MDB и передается службе Singleton вместе с уведомлением о новом сообщении (в основном MDB аннотирует инъекции этих EJB и EM и создает новый контекст выполнения, передавая эти внедренные экземпляры).

Проблема в том, что обработка сущности запускается, но EntityManager в какой-то момент времени (через несколько секунд) начинает возвращать нули для поисковых запросов, а этого быть не должно, так как буквально секунду назад сущность была обновлена.

Похоже, что с архитектурой не все в порядке. Я подозреваю, что поведение EM является признаком того, что контекст персистентности исчез через некоторое время после взаимодействия между MDB и Singleton. Срок службы синглтона намного больше, чем срок жизни любого управляемого компонента в системе. Таким образом, внедрение экземпляров EJB (и экземпляра EM) в такой компонент, по-видимому, вообще не является решением (передача ссылок на внедренные экземпляры EJB из MDB в Singleton, вероятно, является худшим решением).

Возможно, EJB, а также EM должны искаться синглтоном с использованием JNDI каждый раз, когда они нужны? В этом случае следует ли блокировать EJB для каждого вызова?

Как бы вы спроектировали систему: если бы MDB регистрировала только сообщения (как сущности). И обработка сущностей может начаться позже. И вы должны использовать некоторые службы EJB (локальный интерфейс). А еще есть Entity Manager.


person aillusions    schedule 13.12.2012    source источник


Ответы (1)


Если диспетчер сущностей, который использует Singleton, относится к области транзакции, то время существования Singleton не имеет значения. В некотором смысле сеансовые компоненты без сохранения состояния также имеют бесконечное время жизни после создания (их область действия по существу «нет», но их экземпляры объединяются в пул и продолжают использоваться повторно).

Каждый раз, когда метод в синглтоне обслуживает запрос, запускается новая транзакция, и к ней привязывается новый контекст сохранения, даже если экземпляр диспетчера сущностей кажется одним и тем же во всех этих запросах. Это нормальное поведение, и оно не должно "внезапно" возвращать нули.

Возможно, стоит проверить, использует ли ваш синглтон соответствующие блокировки. Если к диспетчеру сущностей обращаются одновременно, это может быть причиной неопределенного поведения.

person Arjan Tijms    schedule 13.12.2012
comment
EM используется одновременно, но один объект обрабатывается в выделенном потоке в последовательности (поток создается для каждого объекта, который вытягивается из очереди Singleton). Очередь содержит идентификаторы сущностей. И как только поток запускается, подключенный EM используется для поиска объекта по этому идентификатору. На первых этапах обработки объект последовательности кажется не нулевым и имеет правильно инициализированные элементы (ссылки). На дальнейших шагах объект может не возвращаться EM по ID или элементы объекта могут быть заполнены неправильно, например. коллекции отношений могут быть нулевыми и т. д. - person aillusions; 13.12.2012
comment
› Одновременно используется EM. Если это действительно так, то практически все ставки сняты. На самом деле не имеет значения, обрабатываете ли вы отдельные объекты в одном потоке. С общим EM поведение не определено, и идея неопределенного поведения заключается просто в том, что вы не можете объяснить его логикой, не зная всех запутанных деталей реализации (на которые вы в любом случае не должны полагаться). Так что решение должно быть довольно простым; не делитесь менеджером сущностей. - person Arjan Tijms; 13.12.2012
comment
Спасибо. Я думаю, вы правы, серия запросов к EM для поиска одного и того же объекта с небольшой паузой между ними дает разные результаты. Как мне создать отдельные экземпляры EM для разных потоков? Использование EntityManagerFactory? - person aillusions; 14.12.2012
comment
Самый простой способ, вероятно, состоит в том, чтобы внедрить диспетчер сущностей в bean-компонент @Stateless, внедрить этот bean-компонент в singleton и делегировать ему операции сохранения. Bean-компонент без сохранения состояния автоматически является потокобезопасным (каждый одновременный вызов его будет тайно маршрутизироваться в другой экземпляр). - person Arjan Tijms; 14.12.2012