|
|
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
Здравствуйте! Вот потихоньку начал ковырять java ee. И возникла проблема, которую ну никак решить не могу - туплю зверско. Есть класс Main @Singleton @Startup. Инжектится TimerService, EntityManager (EntityManagerFactory). В методе @PostConstruct создается таймер. По событию таймера нужно запустить долгий процесс (для этого стартуем поток). В этом процессе нужно скидывать инфу в БД. Примерный код такой: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Это простой пример, на самом деле процесс может занимать час-два. Не суть. Если запускать без потока, то все работает (em беру заинжектенный), если в потоке, то никак не могу заставить заработать. Сервер Wildfly 9.0.2. Приложение Enterprise (EAR+EJB+WEB). ProjectSchedule, ProjectLog - entities. Может есть смысл по-другому построить все? В данном примере ничего не происходит. Все работает, но в БД ничего не вставляется. При попытке использовать транзакции em - NullPointerException. Скорее я просто не понимаю концепцию EE/Beans или еще как торможу. Буду признателен за любые советы. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:07 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
Немного накосячил с сорцами, пока выкладывал: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:16 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymkaПо событию таймера нужно запустить долгий процесс (для этого стартуем поток). Скорее я просто не понимаю концепцию EE... Если вы собираетесь понять концепции EE, то начните хотя бы с чтения EE спецификации. Это относительно небольшой PDF документ, который в конкретные технологии не углубляется. И в нем написано, что согласно EE вам строго на строго не рекомендуется писать код вида new Thread().start(); Причина этого достаточно банальна. Контейнер создаёт кучу ThreadLocal для каждого потока и хранит там массу контекста. EM aka Unit Of Work имеет тот же жизненный цикл как и запрос-ответ. И каждый запрос использует свой собственный экземпляр EM. И как же серверу это удаётся? Именно через ThreadLocal. Когда вы создаёте свой собственный поток, то сервер понятия не имеет что к нему и как привязать. Какая глубокая нужда вас заставила использовать Thread.start() - не понятно. Если вы уже используете JEE таймер, то он и так должен быть многопоточным и асинхронным к клиентским запросам. Какую задачу вы пытаетесь решить запустив асинхронный процесс внутри асинхронного процесса? Ну, если нужна какая-то в этом есть, то в JEE API есть и классы для запуска асинхронных задач. java.lang.Thread к ним не относится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:16 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, ну глупый пока я в EE ))) Почитаю спеки. Если без потоков я делаю sleep (эмулирую длительность, хотя может тоже неверно так) внутри @timeout, то повторный вызов по следующему таймеру почему-то ждет выполнения первого. Я так и думал что timeout асинхронный. Может от настроек AS зависит, но по таймеру там нет ничего толком. Или я неверно интерпретировал записи, которые оказываются в БД. Время старта следующего timeout оказывается смещенным на время задержки-интервал расписания. Поразбираюсь еще с этим. Thread.start - да первое, что попалось на глаза. Как таковых клиентских запросов нет. Это как бы крутится само собой. Синглтон и стартап. Может запускаться несколько процессов, могут быть асинхронными. А какой лучше взять для этой цели класс для запуска асинхронной задачи? Ну если с таймером не разберусь? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:43 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymkaА какой лучше взять для этой цели класс для запуска асинхронной задачи? тут найдеш, меня тоже Blazkowicz научил :-) http://stackoverflow.com/questions/4691132/how-to-run-a-background-task-in-a-servlet-based-web-application ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:56 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymka, https://docs.jboss.org/author/display/WFLY8/EJB3 subsystem configuration guide Смотрите настройки Timer Service и его thread pool ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:56 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymka, Вот ещё доступная статья http://blog.chris-ritchie.com/2013/09/how-to-configure-scheduled-tasks-in-wildfly..html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.05.2016, 19:58 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, rema174 большое спасибо! Пока сделал так, хотя опять не уверен ни в чем :). Если что-то тут работает, то это не означает, что все сделано правильно... Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. В конфиге все ок - пул = 10. Этого мне достаточно. 1. Собственно вопрос - можно делать такие таймауты? Или это не по "феншую"? 2. Или все же использовать ScheduleExecutorService? 3. Если мне больше объект log не нужен - правильно делать detach? 4. И если все же произойдет повторный вход в timeout с истечением времени AccessTimeout, то можно ли каким-либо образом перехватить этот Exception? 5. И еще вопрос: если я в качестве Info таймера передаю сущность, то она приходит в таймер, но без объектов OneToMany. Они остаются неинициализированными. Поэтому в примере выше я передаю ID и заново делаю запрос. Это нормально? Много, конечно, вопросов, сам буду разбираться еще. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.05.2016, 11:18 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymka1. Собственно вопрос - можно делать такие таймауты? Или это не по "феншую"? Какие такие? Зачем тут вообще таймаут? dymka2. Или все же использовать ScheduleExecutorService? Буква потерялась. Вы таймер от таймаута не отличаете? ScheduledExecutorService имеет все те же проблемы в JEE что и ThreadStart. Если только вы его не создали средствами контейнера. Если его создаёт сам контейнер, то им, скорее всего, можно смело пользоваться. dymka3. Если мне больше объект log не нужен - правильно делать detach? Полагаю что "нет". dymka4. И если все же произойдет повторный вход в timeout с истечением времени AccessTimeout, то можно ли каким-либо образом перехватить этот Exception? Почему "повторный вход" вдруг должен вызывать исключение? dymka5. И еще вопрос: если я в качестве Info таймера передаю сущность, то она приходит в таймер, но без объектов OneToMany. Они остаются неинициализированными. Поэтому в примере выше я передаю ID и заново делаю запрос. Это нормально? Google -> JPA Lazy Initialization. Вообще это странно, что "с пустыми". Должно быть исключение ленивой инициализации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.05.2016, 11:23 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, 1, 4. Если оставить только @Timeout, то если будет запущена по расписанию вторая задача, в то время когда первая еще не закончилась, то выходит следующее: Error invoking timeout for timer: ... javax.ejb.ConcurrentAccessTimeoutException Но вот перегрузил комп, удалил деплой, заново залил и заработало без AccessTimeout... уфф )) 2. Именно, как заинжектенный компонент (@Resource), ибо, как понял, такие правила игры :). Но если будет работать вариант с TimerService и @Timeout - то это мне тоже не надо. Хочу как проще. TimerService так то идеально, если справлюсь. 3. А что нужно сделать, чтобы объект был сохранен в БД, а потом из памяти удален. Т.е. убрать из управления EM. Ладно, сам покопаюсь еще. 5. Да все верно, исключение при обращении к этим свойствам. Неверно выразился. Просто у этого объекта до таймера есть эти объекты, а в timeout они "пропадают" ). На данном этапе освоения технологии меня такие вещи просто обескураживают. Спасибо большое, не хочу больше отнимать чужое время, буду разбираться с тем, что есть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.05.2016, 13:52 |
|
||
|
EntityManager в отдельном потоке
|
|||
|---|---|---|---|
|
#18+
dymka1, 4. Если оставить только @Timeout, то если будет запущена по расписанию вторая задача, в то время когда первая еще не закончилась, то выходит следующее: Error invoking timeout for timer: ... javax.ejb.ConcurrentAccessTimeoutException Это уже нюансы EJB. Если у вас Stateful бин или Singleton, то это вполне логично. EJB пытается обезопасить состояние от конкурентного доступа. А как на счет Stateless бина? Вообще у EJB так много подобных заморочек, что я бы сильно подумал перед тем как предпочесть JEE стэк Spring Framework-у. dymka2. Именно, как заинжектенный компонент (@Resource), ибо, как понял, такие правила игры :). Но если будет работать вариант с TimerService и @Timeout - то это мне тоже не надо. Хочу как проще. TimerService так то идеально, если справлюсь. Ну, тогда должно работать. Да. dymka3. А что нужно сделать, чтобы объект был сохранен в БД, а потом из памяти удален. Т.е. убрать из управления EM. Ладно, сам покопаюсь еще. Ну, как бы ничего не надо делать. EM надо закрыть. Но это контейнер должен сделать и сам при выходе из транзакции. Просто надо убедиться что EM закрывается. А сам объект из памяти потом GC соберет. Это вообще отдельная тема. dymka5. Да все верно, исключение при обращении к этим свойствам. Неверно выразился. Просто у этого объекта до таймера есть эти объекты, а в timeout они "пропадают" ). На данном этапе освоения технологии меня такие вещи просто обескураживают. Ассоциации One2Many по-умолчанию грузятся лениво (отложено). Это надо знать. Это JPA и ORM с кучей подводных нюансов. Ленивые ассоциации имеют внутри ссылку на сессию (EntityManager) и используют его чтобы загрузить зависимости, только тогда когда они действительно нужны. Если в одном потоке EntityManager закрыть (а контейнер это сделает сам по завершении транзакции), то в другом потоке догрузить ассоциации уже нельзя, так как EM закрыт. Можно тупо передать ID и прогрузить объект заново. Все же кэш второго уровня решает. Можно использовать Fetch и загрузить всё что нужно заранее - до закрытия EM. Тогда объект спокойно можно скормить в другой поток. dymkaСпасибо большое, не хочу больше отнимать чужое время, буду разбираться с тем, что есть. Раньше JEE был большим и сложным. Всё нужно было писать руками. Теперь писанины руками меньше, то зато всё большое и сложное осталось внутри скрытым от разработчика. Поэтому понять всё это очень сложно. Технологии очень жирные с кучей подобных нюансов. Но JPA надо изучать. Хороших альтернатив ORM-ам пока не видно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.05.2016, 14:33 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39236889&tid=2124058]: |
0ms |
get settings: |
7ms |
get forum list: |
10ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
69ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
30ms |
get tp. blocked users: |
1ms |
| others: | 235ms |
| total: | 367ms |

| 0 / 0 |
