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:
Is it right way to start dependent service in Boot.scala?
Anyway how is it possible to handle container:stop event?
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.
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()
}
Related
I've been using akka-http for a while now, and so far I've mostly logged things using scala-logging by extending either StrictLogging or LazyLogging and then calling the:
log.info
log.debug
....
This is kinda ok, but its hard to understand which logs were generated for which request.
As solutions for this go, I've only seen:
adding an implicit logging context that gets passed around (this is kinda verbose and would force me to add this context to all method calls) + custom logger that adds the context info to the logging message.
using the MDC and a custom dispatcher; in order to implement this approach one would have to use the prepare() call which has just been deprecated.
using AspectJ
Are there any other solutions that are more straightforward and less verbose ? It would be ok to change the logging library btw..
Personally I would go with implicit context approach. I'd start with:
(path("api" / "test") & get) {
val context = generateContext
action(requestId)
}
Then I'd would make it implicit:
(path("api" / "test") & get) {
implicit val context = generateContext
action
}
Then I would make the context generation a directive, like e.g.:
val withContext: Directive1[MyContext] = Directive[Tuple1[MyContext]] {
inner => ctx => inner(Tuple1(generateContext))(ctx)
}
withContext { implicit context =>
(path("api" / "test") & get) {
action
}
}
Of course, you would have to take context as an implicit parameter to every action. But, it would have some advantages over MDC and AspectJ - it would be easier to test things, as you just need to pass value. Besides, who said you only ever need to pass request id and use it for logging? The context could as well pass data about logged in user, its entitlements and other things that you could resolve once, use even before calling action and reuse inside action.
As you probably guessed, this would not work if you want the ability to e.g. remove logging completely. In such case AspectJ would make more sense.
I would have most doubts with MDC. If I understand correctly it has build in assumption that all logic would happen in the same thread. If you are using Futures or Tasks, could you actually guarantee such thing? I would expect that at best all logging calls would happen in the same thread pool, but not necessarily the same thread.
Bottom line is, all possible posiltions would be some variant of what you already figured out, so the question is your exact use case.
I am new to Scala, the PlayFramework, and Dependency Injection. I downloaded the sample scala play framework code. Can someone explain to me why we need to inject the Clock and the appLifeCycle? It is referenced above, so there is no need to inject it right? What is going on here? Why do we need to do this for Web Frameworks in general?
package services
import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future
/**
* This class demonstrates how to run code when the
* application starts and stops. It starts a timer when the
* application starts. When the application stops it prints out how
* long the application was running for.
*
* This class is registered for Guice dependency injection in the
* [[Module]] class. We want the class to start when the application
* starts, so it is registered as an "eager singleton". See the code
* in the [[Module]] class to see how this happens.
*
* This class needs to run code when the server stops. It uses the
* application's [[ApplicationLifecycle]] to register a stop hook.
*/
#Singleton
class ApplicationTimer #Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {
// This code is called when the application starts.
private val start: Instant = clock.instant
Logger.info(s"ApplicationTimer demo: Starting application at $start.")
// When the application starts, register a stop hook with the
// ApplicationLifecycle object. The code inside the stop hook will
// be run when the application stops.
appLifecycle.addStopHook { () =>
val stop: Instant = clock.instant
val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
Future.successful(())
}
}
I assume you're using Lightbend's Play Scala Seed, which contains the code sample that you posted.
If you look at the documentation for java.time.Clock, you'll notice it says (emphasis mine):
Best practice for applications is to pass a Clock into any method that requires the current instant. A dependency injection framework is one way to achieve this. {.. code sample omitted .. } This approach allows an alternate clock, such as fixed or offset to be used during testing.
Ultimately theĀ purpose of dependency injection is to allow you to define the interface that you want to inject into a class or an object, and configure the implementation of that interface in just one spot. The alternative is having to update a hardcoded dependency in multiple files, which can be messy and error prone. In the Play Scala Seed project, you'll notice a file called app/Module.scala. This file is one place where you can configure the bindings and they'll automatically be bound on application start. Notice the line where we bind the Clock implementation:
class Module extends AbstractModule {
override def configure() = {
// Use the system clock as the default implementation of Clock
bind(classOf[Clock]).toInstance(Clock.systemDefaultZone)
// Ask Guice to create an instance of ApplicationTimer when the
// application starts.
bind(classOf[ApplicationTimer]).asEagerSingleton()
// Set AtomicCounter as the implementation for Counter.
bind(classOf[Counter]).to(classOf[AtomicCounter])
}
}
This configuration is saying "when my application starts up, wherever I've injected a Clock should use Clock.systemDefaultZone." If you want ApplicationTimer to use a different clock during tests, you might do something like this:
import play.api.{Environment, Mode}
// Notice that we include the environment
class Module(environment: Environment) extends AbstractModule {
override def configure() = {
// Use the system clock as the default implementation of Clock
environment.mode match {
case Mode.Prod | Mode.Dev => {
bind(classOf[Clock]).toInstance(Clock.systemDefaultZone)
}
case Mode.Test => {
// Specifically use UTC clock in tests, because maybe it's easier to write assertions that way
// You could inject anything here and the ApplicationTimer would use it during tests
bind(classOf[Clock]).toInstance(Clock.systemUTC())
}
}
bind(classOf[ApplicationTimer]).asEagerSingleton()
bind(classOf[Counter]).to(classOf[AtomicCounter])
}
}
You can define modules in other places in the root package (i.e. no package com.example.whatever declaration at the top of the file) and they'll be automatically loaded, too. Otherwise, you'll need to add a binding in conf/application.conf that adds your module's name to the play.modules.enabled key. You can see a commented-out example of that in the Play Scala Seed. I also go into more depth in another answer that I've written here.
As for ApplicationLifecycle, this is a special module provided by Play that you could override with your own binding, but I'm not sure why you'd want to. It's there to give you access to hooks that execute before the application shuts down. Again, this component is injected because it would be simple to swap it out. Imagine having 100 modules that all depend on the application lifecycle. By default, it's bound to DefaultApplicationLifecycle (you can see it being bound here). If you had hardcoded DefaultApplicationLifecycle in all 100 modules, you'd have to update each one if you wanted to switch to a different lifecycle. With dependency injection, you just need to configure the binding to use a different lifecycle and the 100 modules will automatically use it.
I am using protractor to test an angular app which I configured to restart the browser after each test in conf file. However it leads to session errors. I was able to trace this to a helper class I setup that uses expected conditions.
'use strict';
let EC = browser.ExpectedConditions;
let timeOut = 30000;
class ProHelper {
constructor() {}
async waitForUrl(urlSubstring, time = timeOut) {
let isMatchingUrl = EC.urlContains(urlSubstring);
await browser.wait(isMatchingUrl, time, `Timed out waiting for ${urlSubstring}`);
}
...
}
module.exports = ProHelper
The helper class is used inside the page object classes and in some specs. The first test runs fine. However the second one will fail as soon it uses one of the helper methods. It seems the helper methods are still referencing the original browser instance. I tried declaring EC inside the constructor and inside the methods but I get the same error. Is there any way I can re-initialize the helper class after a browser restart?
I made a few changes to get around the issue.
Removed the use of the helper from the specs. It is now only used in the page object classes.
Second I changed browser.ExpectedConditions; to protractor.ExpectedConditions.
Instead of using restartBrowserBetweenTests I added browser.restart() in afterEach for each spec.
That solved my session issue.
We are currently using the Play Framework and we are using the standard logging mechanism. We have implemented a implicit context to support passing username and session id to all service methods. We want to implement logging so that it is session based. This requires implementing our own logger. This works for our own logs but how do we do the same for basic exception handling and logs as a result. Maybe there is a better way to capture this then with implicits or how can we override the exception handling logging. Essentially, we want to get as many log messages to be associated to the session.
It depends if you are doing reactive style development or standard synchronous development:
If standard synchronous development (i.e. no futures, 1 thread per request) - then I'd recommend you just use MDC, which adds values onto Threadlocal for logging. You can then customise the output in logback / log4j. When you get the username / session (possibly in a Filter or in your controller), you can then set the values there and then and you do not need to pass them around with implicits.
If you are doing reactive development you have a couple options:
You can still use MDC, except you'd have to use a custom Execution Context that effectively copies the MDC values to the thread, since each request could in theory be handled by multiple threads. (as described here: http://code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/)
The alternative is the solution which I tend to use (and close to what you have now): You could make a class which represents MyAppRequest. Set the username, session info, and anything else, on that. You can continue to pass it around as an implicit. However, instead of using Action.async, you make your own MyAction class which an be used like below
myAction.async { implicit myRequest => //some code }
Inside the myAction, you'd have to catch all Exceptions and deal with future failures, and do the error handling manually instead of relying on the ErrorHandler. I often inject myAction into my Controllers and put common filter functionality in it.
The down side of this is, it is just a manual method. Also I've made MyAppRequest hold a Map of loggable values which can be set anywhere, which means it had to be a mutable map. Also, sometimes you need to make more than one myAction.async. The pro is, it is quite explicit and in your control without too much ExecutionContext/ThreadLocal magic.
Here is some very rough sample code as a starter, for the manual solution:
def logErrorAndRethrow(myrequest:MyRequest, x:Throwable): Nothing = {
//log your error here in the format you like
throw x //you can do this or handle errors how you like
}
class MyRequest {
val attr : mutable.Map[String, String] = new mutable.HashMap[String, String]()
}
//make this a util to inject, or move it into a common parent controller
def myAsync(block: MyRequest => Future[Result] ): Action[AnyContent] = {
val myRequest = new MyRequest()
try {
Action.async(
block(myRequest).recover { case cause => logErrorAndRethrow(myRequest, cause) }
)
} catch {
case x:Throwable =>
logErrorAndRethrow(myRequest, x)
}
}
//the method your Route file refers to
def getStuff = myAsync { request:MyRequest =>
//execute your code here, passing around request as an implicit
Future.successful(Results.Ok)
}
I have a Logger class that logs events in my application. While I only need one instance of the logger in this application, I want this class to be reusable, so I don't want to make it a singleton and couple it with my specific needs for this application.
I want to be able to access this Logger instance from anywhere in the application without having to create a new one every time or pass it around to every class that might need to log something. What I currently do is have an ApplicationUtils singleton that I use as the point of access for the application's Logger:
object ApplicationUtils {
lazy val log : Logger = new Logger()
}
Then I have a Loggable trait that I add to classes that need the Logger:
trait Loggable {
protected[this] lazy val log = ApplicationUtils.log
}
Is this a valid approach for what I am trying to accomplish? It feels a little hack-y. Is there a better approach I could be using? I'm pretty new to Scala.
Be careful when putting functionality in objects. That functionality is easily testable, but if you need to test clients of that code to make sure they interact with it correctly (via mocks and spies), you're stuck 'cause objects compile to final classes and thus cannot be mocked.
Instead, use this pattern:
trait T { /* code goes here */ }
object T extends T /* pass this to client code from main sources */
Now you can create Mockito mocks / spies for trait T in your test code, pass that in and confirm that the interactions of the code under test with the trait T code are what they should be.
If you have code that's a client of T and whose interactions with it don't require testing, you can directly reference object T.
To address what you're trying to do (rather than what you're asking), take a look at TypeSafe's scalalogging package. It provides a Logging trait that you can use like so:
class MyClass extends Logging {
logger.debug("This is very convenient ;-)")
}
It's a macro-based wrapper for SLF4J, so something like logger.debug(...) gets compiled as if (logger.isDebugEnabled) logger.debug(...).