2014-01-14 201 views
2

我們發現,當從開發中的Jetty移動到生產中的Tomcat時,我們的Swagger文檔停止工作 - 直到首次調用提供該操作的servlet之後,纔會在Swagger文檔中顯示任何操作。如何在啓動時初始化()/初始化()一個Scalatra servlet?

在調試器中進行了一些工作後,我們將問題追溯到未調用servlet的方法init()。我假設Jetty將所有servlet視爲啓動時加載,而Tomcat不是,除非您在web.xml中明確告知它。

不幸的是,在web.xml中,您可以設置爲啓動時加載的唯一東西是servlet,我們的Scalatra web.xml中沒有實際的servlet,只有偵聽器和servlet映射。

我們如何讓Scalatra在啓動時初始化我們的各種ScalatraServlets


注:我們上了Scalatra 2.2.2。很有可能轉向2.3快照或里程碑可以解決Swagger問題,但是我們已經做了很多工作來使2.2 Swagger集成起作用,並且我們太接近不了了之。

回答

2

編輯:這使得它的方式進入了Scalatra和應該不久就會公佈,請參閱https://github.com/scalatra/scalatra/pull/356

是,Tomcat的默認情況下不,直到第一個HTTP請求,它是由加載一個Servlet。你可以告訴Tomcat使用load-on-startup加載Servlet。下面是一個方法來執行此編程使用LifeCycle

def mountServlet(sc: ServletContext, servlet: HttpServlet, urlPattern: String, loadOnStartup: Int = 1) { 
    val name = servlet.getClass.getName 
    val reg = Option(sc.getServletRegistration(name)) getOrElse { 
    val r = sc.addServlet(name, servlet) 
    servlet match { 
     case s: HasMultipartConfig => 
     r.setMultipartConfig(s.multipartConfig.toMultipartConfigElement) 
     case _ => 
    } 
    if (servlet.isInstanceOf[ScalatraAsyncSupport]) 
     r.setAsyncSupported(true) 
    r.setLoadOnStartup(loadOnStartup) 
    r 
    } 

    reg.addMapping(urlPattern) 
} 

這定義在RichServletContext所述mount方法的替代方法。重要的部分是r.setLoadOnStartup(loadOnStartup)

您可以使用它像這樣:

override def init(context: ServletContext) { 

    val comments = CommentsRepository(mongoColl) 

    // mount the api + swagger docs 
    mountServlet(context, new CommentsApi(comments), "/api/*", 1) 
    mountServlet(context, new CommentsApiDoc(), "/api-docs/*", 2) 

    mountServlet(context, new CommentsFrontend(comments), "/*") 

} 

的示例代碼是從https://github.com/scalatra/scalatra-in-action/blob/d325c85feaf10706951c8edb88a3d82d0488faf3/comments-collector/src/main/scala/ScalatraBootstrap.scala拍攝。