|
|
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
Коллеги, Нужна ваша помощь. Так как не знаю как получше реализовать следующая задачу: 1) Есть контроллер который в свою очередь вызывает сервис. 2) Сервис в свою очередь выполняет какой то процесс и может делать это очень долго 3) Есть другой контроллер при вызове которого происходит останов процесса запущенного в п.2 В упрощенной форме эт выглядит так: 1) Пользователь на странице в веб-браузере нажимает кнопку start 2) Пользователь в какой то момент считает что хватит на сегодня выполнять процесс и нажимает кнопку stop опять же на странице в браузере И думается что задачу нужно делать через event'ы, но так как я собственно event'ы не имел необходимости разрабатывать то не могу понять как задачу можно реализовать. Некоторый код моих контроллеров и сервис, выглядит бредово ибо не работает :) Вызывающий сервис, контроллер: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Останавливающий сервис, контроллер: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Сам сервис: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. EventProducer он собственно располагается в контексте сервера-приложений, чтобы любой сервис\контроллер имел к нему доступ: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2015, 17:35 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
TepKuH, Без лишней сущности Event код работает? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2015, 09:32 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
Вам сначала с потоками надо подружиться. Thread Его методом interupt() Знанием почему метод stop() deprecated и как правильно останавливать потоки. Java Concurrency Utilities Особенно ExectorService/Executors FutureTask Потом можно ознакомиться с аннотацией Spring @Async, раз уже этот фреймверк используется. И только потом можете почитать про события, ибо оно тут не совсем к месту. На самом деле реализация сводится к простому. Делем в JobService метод, который возвращает FutureTask и помечаем его @Async Метод обязательно должен вызываться из другого класса (Например контроллера), чтобы проходить через Spring AOP. Тогда этот метод будет запускать задачу в фоновом потоке и в контексте Spring - так что все инъекции должны быть доступны. FutureTask можно кинуть в сессию. Хотя придется озаботиться о сериализации. Можно просто в Map сложить про Session Id. При вызове stop - по session id достаётся ссылка на этот FutureTask и отменяется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2015, 09:40 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
В мануале масса примеров http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html С FutureTask я прогнал: Код: java 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2015, 09:43 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
BlazkowiczВам сначала с потоками надо подружиться. Thread Его методом interupt() Знанием почему метод stop() deprecated и как правильно останавливать потоки. Да идея была в том что есть работающий поток (EJB-компонента), этот поток подписывается на событие. В какой то момент случается эт самое событие(приходит jms) и хелдлер внутри работающей EJB-компоненты выставляет флаг, EJB-компонента в свою очередь постоянно проверяет наличие выставленного флага и в случаи если флаг выставлен в true, просто прекращает работу. Насчет Thread я ведь думал. Там ситуация в том ссылку на thread надо где то хранить (самое очевидно в контексте приложения) но штука в том что у меня в будущем это приложение станет распределенным и нужно будет эту ссылку как то синхронизировать со всеми серверами. Ибо не известно где запущена эта EJB компонента реализующая бизнес-логику. А команда о прекращении может поступить на VIEW сервера где не запущена EJB компонента. BlazkowiczJava Concurrency Utilities Особенно ExectorService/Executors FutureTask Потом можно ознакомиться с аннотацией Spring @Async, раз уже этот фреймверк используется. И только потом можете почитать про события, ибо оно тут не совсем к месту. На самом деле реализация сводится к простому. Делем в JobService метод, который возвращает FutureTask и помечаем его @Async Метод обязательно должен вызываться из другого класса (Например контроллера), чтобы проходить через Spring AOP. Тогда этот метод будет запускать задачу в фоновом потоке и в контексте Spring - так что все инъекции должны быть доступны. FutureTask можно кинуть в сессию. Хотя придется озаботиться о сериализации. Можно просто в Map сложить про Session Id. При вызове stop - по session id достаётся ссылка на этот FutureTask и отменяется. Ваше предложение оно конечно проверено временем, но вот ссылка на Thred... вот что не очень хорошо. Её хранить надо, в случаи же распределенных систем в итоге выйти может зоопарк. А вообще как всегда вам спасибо. Вы постоянно чего то умное мне подсказываете. Я банально тоже хотел нечто подобное сделать, но чутка другими огородами. Ваше предложение более элегантно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2015, 15:20 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
TepKuHДа идея была в том что есть работающий поток (EJB-компонента), этот поток подписывается на событие. В какой то момент случается эт самое событие(приходит jms) и хелдлер внутри работающей EJB-компоненты выставляет флаг, EJB-компонента в свою очередь постоянно проверяет наличие выставленного флага и в случаи если флаг выставлен в true, просто прекращает работу. Насчет Thread я ведь думал. Там ситуация в том ссылку на thread надо где то хранить (самое очевидно в контексте приложения) но штука в том что у меня в будущем это приложение станет распределенным и нужно будет эту ссылку как то синхронизировать со всеми серверами. Ибо не известно где запущена эта EJB компонента реализующая бизнес-логику. А команда о прекращении может поступить на VIEW сервера где не запущена EJB компонента. Ну, так код же выше приведет для Spring. Если надо EJB, то, конечно, Message-Driven Bean в зубы и можно тоже самое ваять. На счет флага мысли верные. Надо только убедится что нет длинных транзкций. TepKuHВаше предложение оно конечно проверено временем, но вот ссылка на Thred... вот что не очень хорошо. Её хранить надо, в случаи же распределенных систем в итоге выйти может зоопарк. А вообще как всегда вам спасибо. Вы постоянно чего то умное мне подсказываете. Я банально тоже хотел нечто подобное сделать, но чутка другими огородами. Ваше предложение более элегантно. Не надо нигде ссылку на Thread хранить. Потоками управляет либо JEE контейнер, либо Spring. Future это не Thread - это ссылка на результат, которого ещё нет, но когда он появится его можно через эту ссылку получить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2015, 16:07 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
BlazkowiczНе надо нигде ссылку на Thread хранить. Потоками управляет либо JEE контейнер, либо Spring. Future это не Thread - это ссылка на результат, которого ещё нет, но когда он появится его можно через эту ссылку получить. Поразмыслил я чутка и покурил чутка про Future<ResultType> я не понял как можно остановить работающий поток нигде не храня при этом ссылку на него. Эт у меня прямо таки ломает мой мозг. У Future есть кучи всяких методов типа Future.cancel(boolean) ну или Future.isDone() но метод нельзя выполнить без ссылки на объект Future. Значит надо его где то хранить и не важно ссылку на что хранить на Thread или на Future. А в случаи распределенной системы надо еще как то сихронизировать эти ссылки. BlazkowiczНу, так код же выше приведет для Spring. Если надо EJB, то, конечно, Message-Driven Bean в зубы и можно тоже самое ваять. На счет флага мысли верные. Надо только убедится что нет длинных транзкций. Эхх, легко сказать возьмите MDB и с песнями. Не получается подписать на события именно тот Bean который начал выполняется :) MDB он ведь по сути обычный Bean с одной оговоркой, он является слушателем слушателем JMS-сообщений, но можно подписать по сути на любые события. Для упрощения я сделаю не классический MDB, а bean который подписал на события ApplicationEvent. Собственно два контроллера, один запускает процесс, другой останавливает. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Далее сам Bean реализующий саму логику Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. Ну и для полноты картины сам event. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. И вот собственно проблема получается в том чтобы именно работающие в данный момент в фоне процессы получали StopJobEvent ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2015, 23:15 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
TepKuH Поразмыслил я чутка и покурил чутка про Future<ResultType> я не понял как можно остановить работающий поток нигде не храня при этом ссылку на него. Потоки не нужно останавливать. Я выше перечислил материал для изучения. Это те основы, которые помогут понять что и как. Ломиться же использовать API, не понимая как он работает, действительно не лучший путь. TepKuH Эт у меня прямо таки ломает мой мозг. У Future есть кучи всяких методов типа Future.cancel(boolean) ну или Future.isDone() но метод нельзя выполнить без ссылки на объект Future. Значит надо его где то хранить и не важно ссылку на что хранить на Thread или на Future. Ссылку на Thread хранит контейнер - Spring, JEE Server или ExecutorService. Реализацию Future тоже предоставляет контейнер. Ты вызываешь cancel() - реализация контейнера, если interrupt запрещен, просто удаляет задачу из очереди. Работающую задачу не прервать. Если interrupt разрешен - то контейнер имеет ссылку на Thread и вызывает interrupt(). Реализация твоего Callable/Runnable должна уметь прерываться по interrupt(). Либо на блокировках, либо проверяя статус текущего потока. TepKuH А в случаи распределенной системы надо еще как то сихронизировать эти ссылки. Это отдельная тема - не надо её сюда приплетать. TepKuH Эхх, легко сказать возьмите MDB и с песнями. Не получается подписать на события именно тот Bean который начал выполняется :) MDB он ведь по сути обычный Bean с одной оговоркой, он является слушателем слушателем JMS-сообщений, но можно подписать по сути на любые события. Для упрощения я сделаю не классический MDB, а bean который подписал на события ApplicationEvent. Продолжай игнорировать то что я пишу. И я тогда буду игнорировать вопросы. Сначала определись на чем делать на EJB или на Spring. В этой задаче их миксовать не нужно. TepKuH Собственно два контроллера, один запускает процесс, другой останавливает. Код: java 1. А ещё я настоятельно рекомендую читать JavaDoc по каждому новому для тебя методу. Future.get() блокирует текущий поток и ждет окончания выполнения задачи в другом потоке. Это не совсем то что тебе нужно. Я же сказал. Future надо складывать в Map по Session Id. И отпускать поток - чтобы вернуть результат зарпоса в клиента (браузер). TepKuH Далее сам Bean реализующий саму логику Код: java 1. 2. 3. 4. 5. 6. 7. 8. TepKuH И вот собственно проблема получается в том чтобы именно работающие в данный момент в фоне процессы получали StopJobEvent Пример через сессию: http://blog.inflinx.com/2012/09/09/spring-async-and-future-report-generation-example/ Важное замечание о том что Future не Serializable и так делать не хорошо. http://blog.inflinx.com/2012/09/09/spring-async-and-future-report-generation-example/#comment-73353 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2015, 09:18 |
|
||
|
Event. Spring framework
|
|||
|---|---|---|---|
|
#18+
BlazkowiczПотоки не нужно останавливать. Я выше перечислил материал для изучения. Это те основы, которые помогут понять что и как. Ломиться же использовать API, не понимая как он работает, действительно не лучший путь. Читал я давно и вспоминал пару дней назад ходя по ссылкам. Я конечно допускаю что я что то упустил. Полагаю что вы хотите мне сказать что потоки нельзя останавливать эт типа не безопасно. Thread.stop() вообще объявлен Deprecated эт я знаю и так. Я в реальности то вообще поток не хочу останавливать, я хочу флаг выставить, а проверять флаг, но эт не суть важно, какой будет флаг какой нить внутри сервиса boolean isStopped или Future.isCancelled() или Thread.isInterrupted() BlazkowiczСсылку на Thread хранит контейнер - Spring, JEE Server или ExecutorService. Реализацию Future тоже предоставляет контейнер. Ты вызываешь cancel() - реализация контейнера, если interrupt запрещен, просто удаляет задачу из очереди. Работающую задачу не прервать. Если interrupt разрешен - то контейнер имеет ссылку на Thread и вызывает interrupt(). Реализация твоего Callable/Runnable должна уметь прерываться по interrupt(). Либо на блокировках, либо проверяя статус текущего потока. Я понял механику Future точно так же. Даже чуть ниже привожу пример где реализовано на Future + проверка текущего статуса Future.isCancelled() внутри сервиса BlazkowiczTepKuH А в случаи распределенной системы надо еще как то синхронизировать эти ссылки. Это отдельная тема - не надо её сюда приплетать. Вот тут бы я поспорил, и сказал бы что эт основная проблема, ссылку на Thread или как вам угодно Future я могу легко кинуть в контейнер эт все очень просто. И пытаться сделать уже Thread.interrupt() или Future.cancel(true). А потом уже в моём работающем методе делать проверку на Thread.isInterrupted(). Сложность в том что у меня в будущем будет несколько серверов приложений. И в этом основная сложность, прошу прощенье что это в начале топика не обозначил BlazkowiczПродолжай игнорировать то что я пишу. И я тогда буду игнорировать вопросы. Сначала определись на чем делать на EJB или на Spring. В этой задаче их миксовать не нужно. Да где же я вас игнорирую то? Я внимательно слушаю, хожу по ссылкам что даёте. Возможно что то упускаю из виду, уж простите меня. Spring использую, с EJB - я прогнал. Думал просто на тот момент про переделку части кода на EJB, и тогда казалось эт здравой мыслью, сейчас уже не кажется. BlazkowiczА ещё я настоятельно рекомендую читать JavaDoc по каждому новому для тебя методу. Future.get() блокирует текущий поток и ждет окончания выполнения задачи в другом потоке. Это не совсем то что тебе нужно. Я же сказал. Future надо складывать в Map по Session Id. И отпускать поток - чтобы вернуть результат запроса в клиента (браузер). Окей, окей, про get() я не читал согласен виноват, потому что у меня работающий метод вообще не возвращает результатов. Не заострял я внимание на том что мне не нужно, взял первый попавший метод. У меня работающий метод читает из cassandra данные, производит с ними математику в циклах (своего рода реализация SQL JOIN'ов) и заполняет кэш ehcache. Дальше из другого потока происходит вычитка данных из кэша. Но в какой то момент времени пользователь может внести изменения в персистентные данные хранящиеся в cassandra (уже в третьем потоке) и в этом случаи производить JOIN'ы не имеет уже смысл - данные то изменились. И должна случится очистка кэша ehcache и начаться история его заполнения снова. Вот тут и нужно рассылать события о прекращении расчетов всем контейнерам которые занимаются расчетами. Т.е. в одном потоке, пользователь говорит, "а сделай ка мне SQL JOIN из noSQL БД :)" - начинается расчет Из другого потока происходит вычитка данных и передача их посредством WebSocket клиенту А из третьего контроллера пользователь решил внести изменения в данные. И вот тут как раз появляется проблема которую пытаюсь решить, эт остановить всех кто ведет расчеты по какой то конкретной ID-таблицы. TepKuH Далее сам Bean реализующий саму логику Код: java 1. 2. 3. 4. 5. 6. 7. 8. Да потому что не случается inject'а с этой аннотацией :) Spring не стартует, а я не стал разбираться почему, сделал как побыстрее лишь бы псевдо код этот нарисовать. Да и не нужны мне вообще результаты которые произведет Future. Мне Future по сути нужен чтобы ему сказать cancel(true) т.е. прибить по возможности. TepKuH И вот собственно проблема получается в том чтобы именно работающие в данный момент в фоне процессы получали StopJobEvent Далее сам код слушающий события (близок к тому что я показал в топике, но с асинхронной реализацией на Future), пока в рамках одного контейнера, но не сложно переделываемый на прослушивающий JMS-сообщения. Код вроде работает за исключением момента когда нужно удалять листнер из хендлера. Мы храним ссылку на JobService, а случись с ним какая то бяда с ним - повис\кинул Exception ссылка не умрёт так и будет вечно хранится в хендлере. Контроллеры: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Сам сервис: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. Handler: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Ну и для полноты картины interface IStopJobListener Код: java 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2015, 15:57 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38852382&tid=2125949]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
169ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
62ms |
get tp. blocked users: |
1ms |
| others: | 237ms |
| total: | 510ms |

| 0 / 0 |
