Подтвердить что ты не робот

Динамично (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 после неудачной перезагрузки?

4b9b3361

Ответ 1

Я не думаю, что это может быть достигнуто без использования контейнера сервлета, который поддерживает горячие развертывания. По моему опыту, хороший способ сделать это - использовать контейнер, поддерживающий OSGi. Вы можете посмотреть Eclipse Virgo или Apache Karaf.

Например, в среде OSGi вы можете создавать модули (называемые пакетами), которые можно отбросить в отсканированную папку, чтобы включить функции во время выполнения или удалить из папки, чтобы отключить некоторые функции. Это похоже на то, как плагины работают в Eclipse IDE, где новая установка/удаление плагина необязательно требует перезапуска.

Ответ 2

Джерси не является технически контейнером сервлетов, это среда REST/JaxB, работающая на контейнере сервлетов.

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

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