2015-11-26 85 views
22

我需要在Jersey ServletContainer中熱部署和 - 部署資源。在Jersey中動態(不)部署資源

似乎有沒有辦法在ResourceConfig「註銷」的資源,所以我下面的路徑是用新的一套替換的所有資源。

雖然the documentation上說ResourceConfig registerResources替換所有資源,通過源代碼瀏覽似乎違背這一點。

我找到的解決方案是一個全新的ResourceConfig重新加載ServletContainer。

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方法中的異常,這是由ServiceLocatorImpl的preDestroy方法中的checkState引起的。

我可以忽略驗證錯誤

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

沒有辦法然而現在,以找出是否有,但探索的記錄,這是一樣糟糕的錯誤避免該異常,真的。

heenenee's comment我試過繼承ServletContainer,但類似的東西給出了問題,因爲ResourceConfig不能放在兩個WebComponents中。

我試圖創建關停,讓早早退出前WebComponent的,但如果在資源沒有錯誤(因爲WebComponent的創建後的resourceconfig不能修改)

失敗的實際重裝
@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); 
} 

有沒有另一種方法來熱卸載資源?重新啓動失敗後,有沒有辦法重置ServletContainer?

+0

你可以嘗試子類'ServletContainer',重載'reload(ResourceConfig)'來捕獲'RuntimeException'並記錄一個錯誤,然後在你的web.xml中指定你的子類。 – heenenee

回答

1

如果不使用支持熱部署的servlet容器,我不認爲這可以實現。根據我的經驗,這樣做的一個好方法是使用支持OSGi的容器。你可以看看Eclipse VirgoApache Karaf

例如,在OSGi環境中,可以創建可下降到掃描文件夾在運行時,以使特徵,或除去從文件夾中的模塊(叫做包),以禁用某些功能。這與插件在Eclipse IDE中的工作方式類似,其中新的插件安裝/卸載不一定需要重新啓動。

+0

我同意。這正是模塊化Web應用程序的用例。您只需在OSGi容器中發佈使用@Path註釋的JAX-RS服務,以滿足預定義的接口。 Servlet實現(也是一個包)將找到你的服務並通過HTTP發佈。 OSGi容器負責在運行時將服務和servlet連接在一起。 – Leo

0

球衣在技術上不是一個servlet容器,它是在一個servlet容器中運行REST/JAXB框架。

大多數嵌入式servlet容器,Tomcat的,碼頭,灰熊可以讓您重新部署應用程序和servlet在運行時。但重新部署通常不是您在將代碼嵌入容器時所使用的功能。

重新部署在生產中最爲有用,可以讓您不斷部署新版本。 在Tomcat上,您可以在同一臺服務器上部署應用程序的新版本和舊版本,並且tomcat可確保在應用程序上的最新版本上啓動新會話,但舊版本將繼續使用它們的啓動應用程序版本。當應用程序不使用loger時,會自動取消部署。