Question

A have lift app starting ssh daemon in Boot.scala. Here is the problem: when i run container:restart / in sbt session I get Address alread in use exception. Now two questions:

  1. Is it right way to start dependent service in Boot.scala?
  2. Anyway how is it possible to handle container:stop event?
Was it helpful?

Solution

I think the Lift-y way to do it is with LiftRules.unloadHooks.

It's not well-documented (AFAIK), but if you look in the Lift source code, you'll see that when the LiftServlet is destroy()ed, the functions defined in LiftRules.unloadHooks are executed.

You can add functions to the unloadHooks RulesSeq with the append or prepend method, depending on what order you want them executed in. So, in your bootstrap.liftweb.Boot.boot method, you might do something like this:

sshDaemon.start()
LiftRules.unloadHooks.append( () => sshDaemon.stop() )

(Assuming that was how you started and stopped your SSH daemon.)

I'm not 100% certain the LiftServlet.destroy() method gets invoked when the sbt web-plugin's container:restart command is run - that's determined by the plugin and its interaction with Jetty, not by Lift - but the container:stop command should definitely do the trick.

OTHER TIPS

I'm not familiar with Lift, but this advice should work for any Servlet based web application.

Register a ServletContextListener in your web.xml, and release any resources in the contextDestroyed method. (The startup should be done in the contextCreated method.)

You can use setAttribute / getAttribute to store and later retrieve the server.

Putting this all together:

import javax.servlet.{ServletContextEvent, ServletContextListener}


final class SshListener extends ServletContextListener{
  val attributeKey = "sshServer"

  def contextInitialized(sce: ServletContextEvent) {
    val server = new Server()
    server.start()
    sce.getServletContext.setAttribute(attributeKey, server)
  }

  def contextDestroyed(sce: ServletContextEvent) {
    Option(sce.getServletContext.getAttribute(attributeKey)).foreach(_.asInstanceOf[Server].stop())
  }
}

class Server {
  def start()
  def stop()
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top