在Jersey中动态(un)部署资源

时间:2015-11-26 14:19:46

标签: java jersey jersey-2.0

我需要在Jersey ServletContainer中热部署和-undeploy资源。

似乎无法在ResourceConfig上“取消注册”资源,因此我所遵循的路线是用新集合替换所有资源。

虽然the documentation表示ResourceConfig上的registerResources取代了所有资源,但浏览源代码似乎与此相矛盾。

我找到的解决方案是使用全新的ResourceConfig重新加载ServletContainer。

double

这样可以正常工作,直到我部署导致ModelValidationException的资源。之后,我无法让ServletContainer恢复正常状态。

如果我看一下源代码:

Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);

从WebComponent构造函数抛出ModelValidationException。 之后,任何重新加载调用都会导致onShutdown方法发生异常,这是由ServiceLocatorImpl的preDestroy方法中的checkState引起的。

我可以通过忽略验证错误来避免异常

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);
    }
}

现在没有办法找出是否有任何错误,但要探索记录,这真的很糟糕。

Per heenenee's comment我尝试了对ServletContainer进行子类化,但这样的事情会产生问题,因为ResourceConfig不能放在两个WebComponents中。

我尝试在关闭之前创建WebComponent,以便提前退出​​,但如果资源中没有错误,则无法实际重新加载(因为在创建web组件后无法修改resourceconfig)

ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
    Boolean.TRUE);
container.reload(config);

还有另一种热取消部署资源的方法吗?有没有办法在重新加载失败后重置ServletContainer?

2 个答案:

答案 0 :(得分:1)

我不认为这可以在不使用支持热部署的servlet容器的情况下实现。根据我的经验,这样做的一个好方法是使用支持OSGi的容器。您可以查看Eclipse VirgoApache Karaf

例如,在OSGi环境中,您可以创建可以删除到扫描文件夹的模块(称为软件包),以便在运行时启用功能,或从文件夹中删除功能,以禁用某些功能。这与插件在Eclipse IDE中的工作方式类似,其中新的插件安装/卸载并不一定需要重新启动。

答案 1 :(得分:0)

Jersey在技术上不是servlet容器,它是在servlet容器上运行的REST / JaxB框架。

大多数可嵌入的servlet容器,Tomcat,Jetty,Grizzly允许您在运行时重新部署应用程序和servlet。但是,重新部署通常不是您在代码中嵌入容器时使用的功能。

热重新部署在生产中最有用,允许您不断部署新版本。 在Tomcat上,您可以在同一服务器上部署新旧版本的应用程序,tomcat确保在应用程序的最新版本上启动新会话,但旧版本将继续使用它们启动时的应用程序版本。当应用程序没有使用时,它会自动取消部署。