Динамично (un) развертывание ресурсов в Джерси
Мне нужно развернуть и -undeploy ресурсы в сервисе ServletContainer.
Кажется, что нет способа "отменить регистрацию" ресурсов в ResourceConfig, поэтому следующий маршрут - это замена всех ресурсов новым набором.
Хотя документация говорит, что registerResources на ResourceConfig заменяет все ресурсы, просмотр исходного кода, похоже, противоречит этому.
Решение, которое я нашел, это перезагрузить ServletContainer с полностью новым ResourceConfig.
Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);
Это отлично работает, пока я не развожу ресурс, из-за которого возникает исключение ModelValidationException. После этого я не могу вернуть ServletContainer в правильное состояние.
Если я взгляну на исходный код:
public void reload(final ResourceConfig configuration) {
try {
containerListener.onShutdown(this);
webComponent = new WebComponent(webComponent.webConfig, configuration);
containerListener = webComponent.appHandler;
containerListener.onReload(this);
containerListener.onStartup(this);
} catch (final ServletException ex) {
LOGGER.log(Level.SEVERE, "Reload failed", ex);
}
}
Отличие ModelValidationException от конструктора WebComponent.
После этого любой вызов для перезагрузки приводит к исключению из метода onShutdown, вызванного checkState в методе preDestroy ServiceLocatorImpl.
Я могу избежать исключения, игнорируя ошибки проверки
ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
Boolean.TRUE);
container.reload(config);
Теперь нет никакого способа узнать, были ли какие-либо ошибки, но чтобы исследовать журнал, который так же плох, действительно.
Per комментарий heenenee Я попробовал подкласс SerletContainer, но что-то вроде этого дает проблемы, потому что ResourceConfig нельзя поместить в два WebComponents.
Я попытался создать WebComponent перед завершением работы, чтобы получить ранний выход, но это не позволяет выполнить реальную перезагрузку, если в ресурсах нет ошибки (поскольку ресурсconfig не может быть изменен после создания веб-компонента)
@Override
public void reload(ResourceConfig configuration) {
try {
new WebComponent(new WebServletConfig(this), configuration);
} catch (ServletException e) {
LOGGER.log(Level.SEVERE, "Reload failed", e);
List<ResourceModelIssue> resources = Collections.emptyList();
throw new ModelValidationException(e.getMessage(), resources);
}
super.reload(configuration);
}
Есть ли другой способ для горячего undeploy ресурсов? Есть ли способ reset ServletContainer после неудачной перезагрузки?
Ответы
Ответ 1
Я не думаю, что это может быть достигнуто без использования контейнера сервлета, который поддерживает горячие развертывания. По моему опыту, хороший способ сделать это - использовать контейнер, поддерживающий OSGi. Вы можете посмотреть Eclipse Virgo или Apache Karaf.
Например, в среде OSGi вы можете создавать модули (называемые пакетами), которые можно отбросить в отсканированную папку, чтобы включить функции во время выполнения или удалить из папки, чтобы отключить некоторые функции. Это похоже на то, как плагины работают в Eclipse IDE, где новая установка/удаление плагина необязательно требует перезапуска.
Ответ 2
Джерси не является технически контейнером сервлетов, это среда REST/JaxB, работающая на контейнере сервлетов.
Большинство встраиваемых контейнеров сервлетов, Tomcat, Jetty, Grizzly позволяет повторно развертывать приложения и сервлеты во время выполнения. Но перераспределение обычно не является функцией, которую вы используете, когда вы вставляете контейнер в код.
Горячее перераспределение наиболее полезно в производстве, что позволяет вам постоянно развертывать новые версии.
На Tomcat вы можете иметь новую и старую версию приложения, развернутого на том же сервере, а tomcat гарантирует, что новые сессии будут запущены в новейшей версии приложения, но более старые версии будут продолжать использовать версию приложения, с которой они были запущены. Когда приложение не используется в журнале, оно автоматически не развертывается.