Testing Akka actors that mixin Stash with TestActorRef - scala

I'm running into a problem with an actor that extends Stash and which works perfectly fine when instantiating it with actorOf in a simple ActorSystem. Now I would actually like to write some tests for my stashing actors before using them in my program. But I cannot figure out a way to use an TestActorRef with this actor in my test suite.
The code that works looks like this:
import akka.actor.{Stash, Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
object StashTest {
val config = ConfigFactory.parseString(
"""
|akka.actor.default-mailbox {
| mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox"
|}
""".stripMargin)
}
class StashTestActor extends Stash {
def receive: Actor.Receive = {
case "unstash" =>
unstashAll()
context become print
case msg => stash()
}
def print: Actor.Receive = {
case msg => println(s"Unstashed message: $msg")
}
}
val system = ActorSystem("stashSystem", StashTest.config)
val ref = system.actorOf(Props[StashTestActor])
ref ! "stash me"
ref ! "blah"
ref ! "unstash"
Which prints
Unstashed message: stash me
Unstashed message: blah
But if I try to write a WordSpec test for this actor, it leaves me with some nasty exceptions I can't figure out what they would like me to change in my code.
The test class looks like this
import akka.testkit.{TestActorRef, TestKit}
import akka.actor.{Stash, Actor, ActorSystem}
import org.scalatest.{WordSpecLike, MustMatchers}
import com.typesafe.config.ConfigFactory
class StashTestActor extends Stash {
def receive: Actor.Receive = {
case "unstash" =>
unstashAll()
context become print
case msg => stash()
}
def print: Actor.Receive = {
case msg => println(s"Unstashed message: $msg")
}
}
class StashTest extends TestKit(ActorSystem("testSystem", StashTest.config))
with WordSpecLike
with MustMatchers {
"A simple stashing actor" must {
val actorRef = TestActorRef[StashTestActor]
"stash messages" in {
actorRef ! "stash me!"
}
"unstash all messages" in {
actorRef ! "unstash"
}
}
}
object StashTest {
val config = ConfigFactory.parseString(
"""
|akka.actor.default-mailbox {
| mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox"
|}
""".stripMargin)
}
When running the test, I get following exceptions that are thrown during the instantiation of the TestActorRef.
[ERROR] [08/20/2013 14:19:40.765] [testSystem-akka.actor.default-dispatcher-3] [akka://testSystem/user/$$a] Could not instantiate Actor
Make sure Actor is NOT defined inside a class/trait,
if so put it outside the class/trait, f.e. in a companion object,
OR try to change: 'actorOf(Props[MyActor]' to 'actorOf(Props(new MyActor)'.
akka.actor.ActorInitializationException: exception during creation
at akka.actor.ActorInitializationException$.apply(Actor.scala:218)
at akka.actor.ActorCell.create(ActorCell.scala:578)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:425)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:447)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:262)
at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:244)
at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:284)
at akka.testkit.CallingThreadDispatcher.register(CallingThreadDispatcher.scala:153)
at akka.dispatch.MessageDispatcher.attach(AbstractDispatcher.scala:133)
at akka.actor.dungeon.Dispatch$class.start(Dispatch.scala:84)
at akka.actor.ActorCell.start(ActorCell.scala:338)
at akka.testkit.TestActorRef.<init>(TestActorRef.scala:50)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:141)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:137)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:146)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:144)
at stashActorTest.StashTest$$anonfun$1.apply$mcV$sp(StashTestActor.scala:29)
at stashActorTest.StashTest$$anonfun$1.apply(StashTestActor.scala:28)
at stashActorTest.StashTest$$anonfun$1.apply(StashTestActor.scala:28)
at org.scalatest.SuperEngine.registerNestedBranch(Engine.scala:613)
at org.scalatest.WordSpecLike$class.org$scalatest$WordSpecLike$$registerBranch(WordSpecLike.scala:120)
at org.scalatest.WordSpecLike$$anon$2.apply(WordSpecLike.scala:851)
at org.scalatest.words.MustVerb$StringMustWrapperForVerb$class.must(MustVerb.scala:189)
at org.scalatest.matchers.MustMatchers$StringMustWrapper.must(MustMatchers.scala:6167)
at stashActorTest.StashTest.<init>(StashTestActor.scala:28)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:444)
at sbt.TestRunner.runTest$1(TestFramework.scala:84)
at sbt.TestRunner.run(TestFramework.scala:94)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:224)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:224)
at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:212)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:224)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:224)
at sbt.TestFunction.apply(TestFramework.scala:229)
at sbt.Tests$$anonfun$7.apply(Tests.scala:196)
at sbt.Tests$$anonfun$7.apply(Tests.scala:196)
at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
at sbt.std.Transform$$anon$4.work(System.scala:64)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:244)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: akka.actor.ActorInitializationException: Could not instantiate Actor
Make sure Actor is NOT defined inside a class/trait,
if so put it outside the class/trait, f.e. in a companion object,
OR try to change: 'actorOf(Props[MyActor]' to 'actorOf(Props(new MyActor)'.
at akka.actor.ActorInitializationException$.apply(Actor.scala:218)
at akka.testkit.TestActorRef$$anonfun$apply$2$$anonfun$apply$1.applyOrElse(TestActorRef.scala:148)
at akka.testkit.TestActorRef$$anonfun$apply$2$$anonfun$apply$1.applyOrElse(TestActorRef.scala:147)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33)
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185)
at scala.util.Try$.apply(Try.scala:161)
at scala.util.Failure.recover(Try.scala:185)
at akka.testkit.TestActorRef$$anonfun$apply$2.apply(TestActorRef.scala:147)
at akka.testkit.TestActorRef$$anonfun$apply$2.apply(TestActorRef.scala:153)
at akka.actor.CreatorFunctionConsumer.produce(Props.scala:369)
at akka.actor.Props.newActor(Props.scala:323)
at akka.actor.ActorCell.newActor(ActorCell.scala:534)
at akka.actor.ActorCell.create(ActorCell.scala:560)
... 58 more
Caused by: java.lang.NullPointerException
at akka.actor.UnrestrictedStash$class.$init$(Stash.scala:82)
at stashActorTest.StashTestActor.<init>(StashTestActor.scala:9)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at akka.actor.ReflectiveDynamicAccess$$anonfun$createInstanceFor$2.apply(DynamicAccess.scala:78)
at scala.util.Try$.apply(Try.scala:161)
at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:73)
... 64 more
I don't have any problems with using TestActorRefs with actors that don't extend Stash. So I don't know if it is a configuration error or something else I'm missing.

TestActorRef can't be used together with Stash. TestActorRef requires a CallingThreadMailbox and Stash requires DequeBasedMessageQueueSemantics. The documentation should include this limitation and the error messages should be improved.

Using the default akka dispatcher allowed me to use Stash and TestActorRef:
val myActor = TestActorRef[MyActor](Props(classOf[MyActor]).withDispatcher("akka.actor.default-dispatcher"))
Note that this means your tests will no longer use the default CallingThreadDispatcher and will lose the benefits highlighted in the akka docs

I was able to test actors with Stash like this:
val actor = TestActorRef(Props(new MyActorWithStash()).withDispatcher("deque"))

Related

Why my Wiremock is Not Starting in my Test

I have trait of wiremock like this:
trait WiremockSetup extends BeforeAndAfterAll { self: Suite =>
import WireMockConfiguration._
protected val wiremockServer = new WireMockServer(options().dynamicPort())
override protected def beforeAll(): Unit = {
super.beforeAll()
wiremockServer.start()
}
override protected def afterAll(): Unit = {
wiremockServer.stop()
super.afterAll()
}
}
And I mix the trait in my test class like this
class Foo extends FlatSpec with WiremockSetup{
"Test scneario" should "do something" in {
assert (1 == 1)
}
}
But I am seeing compilation problems like this:
An exception or error caused a run to abort.
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.github.tomakehurst.wiremock.jetty9.JettyHttpServerFactory.buildHttpServer(JettyHttpServerFactory.java:63)
at com.github.tomakehurst.wiremock.WireMockServer.<init>(WireMockServer.java:76)
Why is problem?
Make sure you have this dependency:
"com.github.tomakehurst" % "wiremock-jre8" % "2.22.0"

Scala akka actor system - RuntimeException when loading extension

I am new with scala and I face the following problem.
import akka.actor.Actor
import akka.actor.Props
import akka.event.Logging
import akka.actor.ActorSystem
object test extends App {
val system = ActorSystem("hello-world")
val myActor = system.actorOf(Props[MyActor], "myactor2")
}
class MyActor extends Actor {
val log = Logging(context.system, this)
val props1 = Props[MyActor]
def receive = {
case "test" => log.info("received test")
case _ => log.info("received unknown message")
}
val child = context.actorOf(Props[MyActor], name = "myChild")
}
So when I run it, I receive
[error] (run-main-1) java.lang.RuntimeException: While trying to load extension [akka.actor.InstanceCountingExtension]
java.lang.RuntimeException: While trying to load extension [akka.actor.InstanceCountingExtension]
at akka.actor.ActorSystemImpl.$anonfun$loadExtensions$1(ActorSystem.scala:906)
at scala.collection.Iterator.foreach(Iterator.scala:929)
at scala.collection.Iterator.foreach$(Iterator.scala:929)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1406)
at scala.collection.IterableLike.foreach(IterableLike.scala:71)
...
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: java.lang.ClassNotFoundException: akka.actor.InstanceCountingExtension
at java.lang.ClassLoader.findClass(ClassLoader.java:530)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
The problem is the ActorSystem, but i can't understand why. When I delete the system an myActor everything works fine. It even works when i make it only val system = ActorSystem but then system couldn't create actorOf.
You probably have this setting in your application.conf
akka.library-extensions += "akka.actor.InstanceCountingExtension"
This is an actor system extension used by akka-actor-tests to make assertions about the number of actor instances currently running in a system.
I don't think this is intended as an extension to be used by applications, it is more like a test utility.
However, depending on what you need:
if you just want to run your program, just delete the configuration line above, and all should be fine
if you need the extension for some reason, import akka-actor-tests test jar, or alternatively make sure you got this class available at runtime.
The problem was with the test folder. When I removed the test it started working.

Eclipse will not recognize my Scala main

What I've tried:
Ensuring Scala perspective is set, disabled, set again
Ensuring that I right click on the Object that extends App
I never get 'Run as Scala application...' at this point
Defining an explicit 'main' in Object after removing 'extends App'
What I get is 'Run Configurations..." when I right-click on Object with main(). No matter what I do there, e.g. enter name of Object that extends App or has an explicit main, main() is never found and I get classloader stack trace dumps indicating that there is no main.
While I get no Scala compile errors, no matter what I try, I never get 'Run As...Scala Application'.
Code:
object fatfinger extends App {
import com.mongodb.casbah.Imports._
import Common._
import MongoFactory._ */
object Insert {
def main(args: Array[String]) {
val apple = Stock("AAPL", 600)
val google = Stock("GOOG", 650)
val netflix = Stock("NFLX", 60)
saveStock(apple)
saveStock(google)
saveStock(netflix) }
def saveStock(stock: Stock) {
val mongoObj = buildMongoDbObject(stock)
MongoFactory.collection.save(mongoObj) } }
}
Stacktrace:
Exception in thread "main" java.lang.NoClassDefFoundError: Insert
Caused by: java.lang.ClassNotFoundException: Insert
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

Writing ByteString to File Causing NullPointerException

I've got an Akka actor that reads the contents of a file in chunks of around 1500 bytes. When the actor receives a NextBlock message it replies with the next block of data wrapped in a ByteString. A couple very simple tests and manually eyeballing data indicate the actor is working correctly. I'm using Scala 2.11.5, Akka 2.3.9, ScalaTest 2.2.1 and SBT 0.13.5.
I'm having an issue setting up larger test. I want to write around 10kB or so of a test pattern data into a file then verify the Actor's output is what I expect. I'm creating the test pattern via ByteStringBuilder. When I go to write the test data to the file I'm getting NullPointerExceptions. Here is the code for a striped down version of the test that exhibits the issue:
import java.nio.ByteOrder
import java.nio.file.StandardOpenOption._
import java.nio.file.{Files, Paths}
import akka.actor.ActorSystem
import akka.testkit.TestKit
import akka.util.{ByteString, ByteStringBuilder}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class ByteBufferTest extends TestKit(ActorSystem("ByteBufferTest"))
with WordSpecLike with Matchers with BeforeAndAfterAll {
implicit val byteOrder = ByteOrder.BIG_ENDIAN
val file = Paths.get("test.data")
Files.deleteIfExists(file)
createTestFile()
"A ByteBufferTest" must { "work" in { assert(true) } }
def createTestFile(): Unit = {
val out = Files.newByteChannel(file, CREATE, WRITE)
out.write(contents.toByteBuffer) // Here is where the NPE occurs
out.close()
}
val contents: ByteString = {
val builder = new ByteStringBuilder
(0 to 255).foreach(builder.putInt)
builder.result()
}
override protected def afterAll(): Unit = {
Files.delete(file)
system.shutdown()
}
}
I've tried getting around this a bunch of different ways
converting the ByteString to a ByteBuffer and writing it via ByteChannel (show above)
write individual bytes of the ByteString to a BufferedOutputStream
convert the ByteString to Array[Byte] and write that via BufferedOutputStream
No matter what I try I keep ending up with something along the lines of
[debug] Running TaskDef(demo.ByteBufferTest, org.scalatest.tools.Framework$$anon$1#40fbf2c, false, [SuiteSelector])
java.lang.NullPointerException at demo.ByteBufferTest.createTestFile(ByteBufferTest.scala:32)
at demo.ByteBufferTest.<init>(ByteBufferTest.scala:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
at sbt.TestRunner.runTest$1(TestFramework.scala:84)
at sbt.TestRunner.run(TestFramework.scala:94)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:219)
at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:207)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:219)
at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:219)
at sbt.TestFunction.apply(TestFramework.scala:224)
at sbt.Tests$$anonfun$7.apply(Tests.scala:196)
at sbt.Tests$$anonfun$7.apply(Tests.scala:196)
at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
at sbt.std.Transform$$anon$4.work(System.scala:64)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:244)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Anyone have any ideas what I'm doing wrong?
I've put a example project up on github
I didn't find the exact root cause but it seems that it is related to the initialization when the test class is launched from scala test.
I suggest to put the createTestFile() in the method of beforeAll(). Tested and it works.
override def beforeAll {
createTestFile()
}

Play app can't run after adding scalacOptions in SBT

I've added these Scalac options in my SBT build:
scalacOptions ++= Seq("-unchecked", "-deprecation","-feature"),
But then I can't access my Play 2.1 web application anymore.
It is the only modified part of my build, and if I remove this, it works fine again.
It's weird because the application seems to be running (I see startup logs, scheduled jobs...), but trying to access it from the browser gives me Play error page:
Cannot init the Global object
No source available, here is the exception stack trace:
->java.lang.ExceptionInInitializerError:
Global$.<init>(Global.scala:17)
Global$.<clinit>(Global.scala)
sun.misc.Unsafe.ensureClassInitialized(Native Method)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:140)
java.lang.reflect.Field.acquireFieldAccessor(Field.java:949)
java.lang.reflect.Field.getFieldAccessor(Field.java:930)
java.lang.reflect.Field.get(Field.java:372)
play.api.WithDefaultGlobal$class.play$api$WithDefaultGlobal$$scalaGlobal(Application.scala:37)
play.api.DefaultApplication.play$api$WithDefaultGlobal$$scalaGlobal$lzycompute(Application.scala:383)
play.api.DefaultApplication.play$api$WithDefaultGlobal$$scalaGlobal(Application.scala:383)
play.api.WithDefaultGlobal$$anonfun$play$api$WithDefaultGlobal$$globalInstance$1$$anonfun$apply$5.apply(Application.scala:52)
play.api.WithDefaultGlobal$$anonfun$play$api$WithDefaultGlobal$$globalInstance$1$$anonfun$apply$5.apply(Application.scala:52)
scala.Option.getOrElse(Option.scala:120)
play.api.WithDefaultGlobal$$anonfun$play$api$WithDefaultGlobal$$globalInstance$1.apply(Application.scala:52)
play.api.WithDefaultGlobal$$anonfun$play$api$WithDefaultGlobal$$globalInstance$1.apply(Application.scala:51)
play.utils.Threads$.withContextClassLoader(Threads.scala:18)
play.api.WithDefaultGlobal$class.play$api$WithDefaultGlobal$$globalInstance(Application.scala:50)
play.api.DefaultApplication.play$api$WithDefaultGlobal$$globalInstance$lzycompute(Application.scala:383)
play.api.DefaultApplication.play$api$WithDefaultGlobal$$globalInstance(Application.scala:383)
play.api.WithDefaultGlobal$class.global(Application.scala:66)
play.api.DefaultApplication.global(Application.scala:383)
play.api.WithDefaultConfiguration$class.play$api$WithDefaultConfiguration$$fullConfiguration(Application.scala:80)
play.api.DefaultApplication.play$api$WithDefaultConfiguration$$fullConfiguration$lzycompute(Application.scala:383)
play.api.DefaultApplication.play$api$WithDefaultConfiguration$$fullConfiguration(Application.scala:383)
play.api.WithDefaultConfiguration$class.configuration(Application.scala:82)
play.api.DefaultApplication.configuration(Application.scala:383)
play.api.Application$class.$init$(Application.scala:268)
play.api.DefaultApplication.<init>(Application.scala:383)
play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anon$1.<init>(ApplicationProvider.scala:128)
play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:128)
play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:114)
scala.Option.map(Option.scala:145)
play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:114)
play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:112)
scala.util.Either$RightProjection.flatMap(Either.scala:523)
play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:112)
play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:104)
scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:722)
My Global.scala looks like this:
object Global extends GlobalSettings {
// TODO use cake pattern injection?
val searchService: SearchService = StampleApplication.get.searchService
val breadcrumbService: BreadcrumbService = StampleApplication.get.breadcrumbService
override def onStart(app: Application) {
Logger.info("Application has started")
startElasticSearchIndexationScheduling
startBreadcrumbUpdaterJob
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
// TODO externaliser delais des jobs dans la conf play?
def startElasticSearchIndexationScheduling = {
Akka.system.scheduler.schedule(30 seconds , 30 seconds) {
Logger.info("Indexation job triggered")
searchService.indexUnindexedStamples
searchService.indexUnindexedUsers
}
}
def startBreadcrumbUpdaterJob = {
Akka.system.scheduler.schedule(30 seconds, 30 seconds) {
Logger.info("Breadcrumb updated job triggered")
breadcrumbService.updateChildsBreadcrumbForFlaggedCategories
Logger.info("Breadcrumb updated (with recursion!) job triggered")
breadcrumbService.recompteAllFlaggedWithRecursion
}
}
}
The Global$.(Global.scala:17) seems to reference this line:
val searchService: SearchService = StampleApplication.get.searchService
The rest of the sources are:
object StampleApplication {
val get: CakeApplication = {
println("Building stample cake application")
// Inject properties here
new CakeConfiguration().buildApplication
}
}
trait CakeApplication
extends ServiceLayer
with RepositoryLayer
trait ServiceLayer
extends RepositoryLayer
with DefaultUserServiceComponent
with DefaultCategoryServiceComponent
with DefaultStampleServiceComponent
with DefaultAclServiceComponent
with DefaultFileServiceComponent
with DefaultApiCallServiceComponent
with DefaultBreadcrumbServiceComponent
with DefaultSearchServiceComponent
with DefaultRelationshipServiceComponent
with DefaultSharingServiceComponent
with DefaultAuthCodeServiceComponent
with DefaultNotificationServiceComponent
with DefaultEventServiceComponent
with DefaultCommentServiceComponent
trait RepositoryLayer
extends MongoUserRepositoryComponent
with MongoCategoryRepositoryComponent
with MongoCategorySharingRepositoryComponent
with MongoStampleRepositoryComponent
with MongoFileRepositoryComponent
with MongoApiCallRepositoryComponent
with MongoRelationshipRepositoryComponent
with MongoSharingRepositoryComponent
with MongoNotificationRepositoryComponent
with SalatDAOFactoryComponent
with CollectionProviderComponent
trait CollectionProviderComponent {
def collectionProvider:MongoCollectionProvider
}