Как я могу заставить ServletContextListener останавливать приложение Java EE?

У меня есть ServletContextListener, который выполняет некоторые функции управления базой данных при запуске моего приложения Java EE. Это выполняется в моем приложении до запуска / загрузки JPA и других частей приложения. Если обслуживание базы данных не удается, я регистрирую ошибки. В случае сбоя обслуживания базы данных приложение не будет работать должным образом, и я хотел бы остановить его.

Как изящно и правильно остановить приложение из ServletContextListener.contextInitialized?

Решение, данное ниже Viven, близко, но не совсем. Когда я генерирую исключение RuntimeException, Glassfish остается в несогласованном состоянии, когда его консоль администратора недоступна, но какой-то процесс все еще работает и держит порт 3700 (IIOP?) Открытым, что затем предотвращает перезапуск.


person Freiheit    schedule 11.07.2011    source источник


Ответы (2)


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

На этом этапе ваши варианты могут быть продиктованы архитектурой вашего приложения. Если все запросы обрабатываются одним сервлетом контроллера / диспетчера, может иметь смысл, чтобы его метод init проверял атрибуты контекста и выдавал UnavailableException. Просто имейте в виду, что исключение применяется только к конкретному сервлету, который его выбрасывает. Это делает подход менее управляемым, если ваше приложение содержит много сервлетов или разрешает прямой доступ к другим ресурсам.

Другой вариант - создать фильтр, который перехватывает каждый запрос, проверяет атрибуты контекста и затем генерирует исключение. Конечно, возможны и другие варианты.

person kschneid    schedule 13.07.2011
comment
В моем слушателе я устанавливаю атрибут контекста, а затем реагирую на него в фильтре. Фильтр выдает исключение ServletException (HTTP 500), которое останавливает пользовательский интерфейс, но не останавливает мои веб-службы. Есть ли где-нибудь, где я могу реализовать фильтр (или аналогичный) для проверки этого атрибута контекста? - person Freiheit; 16.07.2011
comment
Не уверен, что вы имеете в виду, когда останавливаете свои веб-службы. Если фильтр настроен на перехват каждого запроса, то каждый запрос должен приводить к исключению. Не могли бы вы подробнее рассказать о веб-службах вашего приложения? - person kschneid; 18.07.2011
comment
Все мои веб-службы используют EnterpriseBeans, в то время как пользовательский интерфейс использует Servlets / ActionBeans. Итак, для пользовательского интерфейса у меня есть фильтр, который может проверять это состояние приложения. Для EnterpriseBeans мне нужно реализовать что-то вроде Iterceptor, чтобы проверять состояние приложения и реагировать соответствующим образом. - person Freiheit; 18.07.2011

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

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

После надлежащей проверки в спецификации такое поведение не является обязательным в спецификации. Сервер может (не должен) возвращать 500 ошибок. Поэтому этот раствор следует использовать осторожно.

См. этот ответ для цитаты из спецификации сервлета.

person Vivien Barousse    schedule 11.07.2011
comment
Если ваш ServletContextListener выдает исключение, веб-приложение не загружается правильно - откуда вы это знаете? Спецификация не определяет ничего подобного. С такой же вероятностью любой сервер приложений просто сообщит об исключении и продолжит работу независимо. ServletContextListener не предназначен для влияния на жизненный цикл приложения. - person skaffman; 12.07.2011
comment
Это описано в параграфе 11.6: Исключения слушателей. - Контейнер может отвечать на все последующие запросы к веб-приложению кодом состояния HTTP 500, указывающим на ошибку приложения. - person Vivien Barousse; 12.07.2011
comment
Ах, достаточно честно. Вы можете дополнить свой исходный ответ URL-адресом и цитатой из этой ссылки. Однако язык слишком запутанный, я бы не хотел полагаться на то, что контейнер может ответить. - person skaffman; 12.07.2011
comment
Только что понял, что на самом деле сказано: «Может, а не должен». Не так точно, как я сначала думал ... - person Vivien Barousse; 12.07.2011
comment
Однако бросание Runtime Exception работает в Glassfish v2.? кажется, что Java-процесс остается запущенным, и порт 3700 остается открытым. Это специфично для Glassfish или общего для J2EE? - person Freiheit; 12.07.2011
comment
Не совсем изящный, но грязный способ - это System.exit, хотя вызов его из сервлета может быть не фантастической идеей. - person Keibosh; 12.07.2011
comment
System.exit(1) ведет себя так же, как RuntimeException, по крайней мере, в Glassfish 2.x - person Freiheit; 12.07.2011
comment
Отправка RuntimeException не останавливает сервер приложений. Это может предотвратить запуск приложения и может отвечать на все последующие запросы к приложению кодом ответа 500 (ошибка сервера). Использование System.exit - очень плохая идея. Он принудительно завершает работу сервера, даже если другие (отлично работающие) приложения развернуты на том же сервере. Раньше я имел дело с приложением, делающим это (Alfresco), и поверьте мне, это более чем раздражает! - person Vivien Barousse; 13.07.2011
comment
Проголосуйте за информацию, но, к сожалению, выброс исключения не остановил для меня запуск сервера. - person Kevin Workman; 27.01.2018