Failed to run simple akka sample using sbt - scala

I'm just following akka sample but could not run the program.
I've installed akka, sbt(0.13), scala(2.10.3) using homebrew(OSX Mountail Lion)
make empty directory named akka_test
create build.sbt and Hello.scala file
run sbt in akka_test directory and compile command worked well
sbt's run command complains No main class detected
What should I do to run the program?
here's my code
build.sbt
name := "My Project"
version := "1.0"
scalaVersion := "2.10.2"
resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
libraryDependencies +=
"com.typesafe.akka" %% "akka-actor" % "2.2.1"
Hello.scala
import akka.actor.Actor
import akka.actor.Props
class HelloWorld extends Actor {
override def preStart(): Unit = {
// create the greeter actor
val greeter = context.actorOf(Props[Greeter], "greeter")
// tell it to perform the greeting
greeter ! Greeter.Greet
}
def receive = {
// when the greeter is done, stop this actor and with it the application
case Greeter.Done ⇒ context.stop(self)
}
}
object Greeter {
case object Greet
case object Done
}
class Greeter extends Actor {
def receive = {
case Greeter.Greet ⇒
println("Hello World!")
sender ! Greeter.Done
}
}

sbt has run-main command which accepts main class from command line,
so full command is
sbt "run-main akka.Main HelloWorld"

sbt run looks for a "main" class, i.e., a class with def main(args: Array[String]) or extends the trait App. Since that can't be an actor, you'll need to initiate a system and use that to initiate HelloWorld, so something like:
class HelloWorldMain {
def main(args: Array[String]) {
import akka.actor.ActorSystem
val system = ActorSystem("HelloWorld")
val helloWorldActor = system.actorOf(Props[HelloWorld] ...)
// ... Do stuff
}
}
Since systems just run until you shut them down, if you want your main class to stop you'll either have to use futures via akka.pattern.ask and have the system terminate after you collect them or set up a separate reaper actor to kill the system for you. This post has more info on how to do that, and this pull request is a good example of how it looks in practice (and has some other useful stuff in there as well)

in case you have package you need to add the path.
For example if you have package com.foo.bar
(your HelloWorld is in ./youProject/src/main/scala/com/foo/bar)
then the command will be:
sbt "run-main akka.Main com.foo.bar.HelloWorld"

Related

How do I load configuration file on startup

I have application.conf file for my Scala program in main/resources. I load the configuration file using Config.load(). It is all working. But my config loading code is inside my service class. I want something like when program starts then first thing it doing is loading configuration. Then I want to use DI to pass this around.
This is easy in Scala Play because I just write Module class and specify in config file. Play then loads my config at start up. But how can I do this with non-Play project - just plain scala program.
Play uses Guice out-of-the-box for dependency injection, so you could consider using the same.
Here is an example of how guice can be used to inject configuration into services:
package example
import com.google.inject.{AbstractModule, Guice, Inject, Injector, Provides, Singleton}
import com.typesafe.config.ConfigFactory
import scala.jdk.CollectionConverters._
case class Config(foo: String, bar: String)
class Module extends AbstractModule {
#Provides
#Singleton
def getConfig: Config = {
val conf = ConfigFactory.load()
Config(
conf.getString("foo"),
conf.getString("bar")
)
}
}
class QuxService #Inject()(config: Config) {
println(config)
}
object ConfigInjectionExample extends App {
val injector: Injector = Guice.createInjector(List(new Module).asJava)
injector.getInstance(classOf[QuxService])
}
which outputs
Config(hello,world)
given the following resources/application.conf
foo="hello"
bar="world"
and the following dependencies
libraryDependencies += "net.codingwell" %% "scala-guice" % "4.2.6",
libraryDependencies += "com.typesafe" % "config" % "1.3.4"

How to get the package of methods or objects in Scala?

How to get the package of methods or objects in Scala?
For example
import scala.math._
round().getClass // errors
Is there a way to get the desired output: "scala.math.round"? So that I can be sure of round() method doesn't come from any other package I've imported.
PS. Without using Intellij IDE. The IDE shows you this info, hence there has to be a function that IDE calls to get this info.
EDIT:
For example, running these commands in scala shell
With Scala reflection (libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value in build.sbt) you can do
import scala.math._
import scala.reflect.runtime.universe._
object App {
def main(args: Array[String]): Unit = {
println(
showRaw(reify {
round(???)
})
)
}
}
Output at runtime will be
Expr(Apply(Select(Ident(scala.math.package), TermName("round")), List(Select(Ident(scala.Predef), TermName("$qmark$qmark$qmark")))))
Or you can add scalacOptions in Compile ++= Seq("-Xprint-types", "-Xprint:typer") to build.sbt.
Then compilation of
package pckg
import scala.math._
object App {
round(???)
}
will produce (at compile time)
Warning:scalac: package pckg{pckg.type} {
import scala.math._;
object App extends scala.AnyRef {
def <init>(): pckg.App.type = {
App.super{pckg.App.type}.<init>{()Object}(){Object};
(){Unit}
}{Unit};
scala.math.`package`.round{(x: Long)Long}(scala.Predef.???{Nothing}){Long}
}
}

Specs2: how to test a class with more than one injected dependency?

Play 2.4 app, using dependency injection for service classes.
I found that Specs2 chokes when a service class being tested has more than one injected dependency. It fails with "Can't find a constructor for class ..."
$ test-only services.ReportServiceSpec
[error] Can't find a constructor for class services.ReportService
[error] Error: Total 1, Failed 0, Errors 1, Passed 0
[error] Error during tests:
[error] services.ReportServiceSpec
[error] (test:testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 2 s, completed Dec 8, 2015 5:24:34 PM
Production code, stripped to bare minimum to reproduce this problem:
package services
import javax.inject.Inject
class ReportService #Inject()(userService: UserService, supportService: SupportService) {
// ...
}
class UserService {
// ...
}
class SupportService {
// ...
}
Test code:
package services
import javax.inject.Inject
import org.specs2.mutable.Specification
class ReportServiceSpec #Inject()(service: ReportService) extends Specification {
"ReportService" should {
"Work" in {
1 mustEqual 1
}
}
}
If I remove either UserService or SupportService dependency from ReportService, the test works. But obviously the dependencies are in the production code for a reason. Question is, how do I make this test work?
Edit: When trying to run the test inside IntelliJ IDEA, the same thing fails, but with different messages: "Test framework quit unexpectedly", "This looks like a specs2 exception..."; see full output with stacktrace. I opened a Specs2 issue as instructed in the output, though I have no idea if the problem is in Play or Specs2 or somewhere else.
My library dependencies below. (I tried specifying Specs2 version explicitly, but that didn't help. Looks like I need specs2 % Test as is, for Play's test classes like WithApplication to work.)
resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"
libraryDependencies ++= Seq(
specs2 % Test,
jdbc,
evolutions,
filters,
"com.typesafe.play" %% "anorm" % "2.4.0",
"org.postgresql" % "postgresql" % "9.4-1205-jdbc42"
)
There is limited support for dependency injection in specs2, mostly for execution environments or command-line arguments.
There is nothing preventing you from just using a lazy val and your favourite injection framework:
class MySpec extends Specification with Inject {
lazy val reportService = inject[ReportService]
...
}
With Play and Guice, you could have a test helper such as this:
import play.api.inject.guice.GuiceApplicationBuilder
import scala.reflect.ClassTag
trait Inject {
lazy val injector = (new GuiceApplicationBuilder).injector()
def inject[T : ClassTag]: T = injector.instanceOf[T]
}
If you really need runtime dependency injection, then it's better to use Guice loading, I guess:
package services
import org.specs2.mutable.Specification
import scala.reflect.ClassTag
import com.google.inject.Guice
// Something you'd like to share between your tests
// or maybe not
object Inject {
lazy val injector = Guice.createInjector()
def apply[T <: AnyRef](implicit m: ClassTag[T]): T =
injector.getInstance(m.runtimeClass).asInstanceOf[T]
}
class ReportServiceSpec extends Specification {
lazy val reportService: ReportService = Inject[ReportService]
"ReportService" should {
"Work" in {
reportService.foo mustEqual 2
}
}
}
Alternatively you can implement Inject object as
import scala.reflect.ClassTag
import play.api.inject.guice.GuiceApplicationBuilder
object Inject {
lazy val injector = (new GuiceApplicationBuilder).injector()
def apply[T : ClassTag]: T = injector.instanceOf[T]
}
It depends whether you want to use Guice directly, or thru play wrappers.
Looks like you are out of luck ATM: The comment says
Try to create an instance of a given class by using whatever constructor is available and trying to instantiate the first parameter recursively if there is a parameter for that constructor.
val constructors = klass.getDeclaredConstructors.toList.filter(_.getParameterTypes.size <= 1).sortBy(_.getParameterTypes.size)
i.e. Specs2 doesn't provide own DI out-of-the box,
Or you can reimplement the functionality yourself, if Guice isn't working for you.
App code:
package services
import javax.inject.Inject
class ReportService #Inject()(userService: UserService, supportService: SupportService) {
val foo: Int = userService.foo + supportService.foo
}
class UserService {
val foo: Int = 1
}
class SupportService {
val foo: Int = 41
}
Test code
package services
import org.specs2.mutable.Specification
import scala.reflect.ClassTag
import java.lang.reflect.Constructor
class Trick {
val m: ClassTag[ReportService] = implicitly
val classLoader: ClassLoader = m.runtimeClass.getClassLoader
val trick: ReportService = Trick.createInstance[ReportService](m.runtimeClass, classLoader)
}
object Trick {
def createInstance[T <: AnyRef](klass: Class[_], loader: ClassLoader)(implicit m: ClassTag[T]): T = {
val constructors = klass.getDeclaredConstructors.toList.sortBy(_.getParameterTypes.size)
val constructor = constructors.head
createInstanceForConstructor(klass, constructor, loader)
}
private def createInstanceForConstructor[T <: AnyRef : ClassTag]
(c: Class[_], constructor: Constructor[_], loader: ClassLoader): T = {
constructor.setAccessible(true)
// This can be implemented generically, but I don't remember how to deal with variadic functions
// generically. IIRC even more reflection.
if (constructor.getParameterTypes.isEmpty)
constructor.newInstance().asInstanceOf[T]
else if (constructor.getParameterTypes.size == 1) {
// not implemented
null.asInstanceOf[T]
} else if (constructor.getParameterTypes.size == 2) {
val types = constructor.getParameterTypes.toSeq
val param1 = createInstance(types(0), loader)
val param2 = createInstance(types(1), loader)
constructor.newInstance(param1, param2).asInstanceOf[T]
} else {
// not implemented
null.asInstanceOf[T]
}
}
}
// NB: no need to #Inject here. The specs2 framework does it for us.
// It sees spec with parameter, and loads it for us.
class ReportServiceSpec (trick: Trick) extends Specification {
"ReportService" should {
"Work" in {
trick.trick.foo mustEqual 2
}
}
}
And that expectedly fails with
[info] ReportService should
[error] x Work
[error] '42' is not equal to '2' (FooSpec.scala:46)
If you don't need runtime dependency injection, then it's better to use cake pattern, and forget reflection all-together.
My colleague suggested a "low-tech" workaround. In the test, instantiate service classes with new:
class ReportServiceSpec extends Specification {
val service = new ReportService(new UserService, new SupportService)
// ...
}
This also works:
class ReportServiceSpec #Inject()(userService: UserService) extends Specification {
val service = new ReportService(userService, new SupportService)
// ...
}
Feel free to post more elegant solutions. I've yet to see a simple DI solution that works (with Guice, Play's default).
Does anyone else find it curious that Play's default test framework does not play well with Play's default DI mechanism?
Edit: In the end I went with an "Injector" test helper, almost the same as what Eric suggested:
Injector:
package testhelpers
import play.api.inject.guice.GuiceApplicationBuilder
import scala.reflect.ClassTag
/**
* Provides dependency injection for test classes.
*/
object Injector {
lazy val injector = (new GuiceApplicationBuilder).injector()
def inject[T: ClassTag]: T = injector.instanceOf[T]
}
Test:
class ReportServiceSpec extends Specification {
val service = Injector.inject[ReportService]
// ...
}

Correction for error: - required:spray.httpx.marshalling.ToResponseMarshallable

I'm new to Scala, and trying to write a little REST API. I am using Scala 11.2, Spray 1.3.1 and akka 2.3.6.
I am basically trying to compile an example from spray.
The error I get for each of the routes is:
type mismatch; found : String("pong!!!!!!!!") required: spray.httpx.marshalling.ToResponseMarshallable
I am unsure if it is a versions incompatibility issue or I am missing a reference.
Here is my route definition taken from the spray example :
package com.Shenandoah.SBIR.httpInterface
import spray.routing.HttpService
trait HttpInterface extends HttpService {
def pingRoute = path("ping") {
get { complete("pong!!!!!!!!") }
}
def pongRoute = path("pong") {
get { complete("pong!?") }
}
def pipRoute = path("pip") {
get { complete("moonshine") }
}
def rootRoute = pingRoute ~ pongRoute ~ pipRoute
}
Here is the actor:
package com.Shenandoah.SBIR.httpInterface
import akka.actor._
class HttpInterfaceActor extends HttpInterface with Actor {
// the HttpService trait defines
// only one abstract member, which connects the services environment
// to the enclosing actor or test.
def actorRefFactory = context
def receive = runRoute(rootRoute)
}
You are probably using the dependency "io.spray" % "spray-routing" % "2.3.6" which is for Scala 2.10. There is a Spray version published without the Scala version designation, which is compiled against Scala 2.10. This is unfortunate.
Use "io.spray" %% "spray-routing" % "2.3.6" (note the double %) to pull in the dependency matching your Scala version. This will work with both Scala 2.10 and 2.11.
Looks like you are missing the default marshallers. Try adding to your imports:
import spray.httpx.marshalling.Marshaller

Basic Spray-Testkit usage to test a route does not work

I am trying to use spray route and want to test it with Spray-TestKit.
I am using :
- Scala 2.10.3
- Akka 2.3.3
- Spray 1.3.1
I create a trait extending HttpService, where I define a route :
trait MyService extends HttpService with CoreAccess {
import greentee.am.endpoint.tsmsp.tsmSPJsonSupport._
val myRoute = {
path("resources"/"ping") {
get {
complete(OK, "pong")
}
}
}
}
I deleted part of the route which was not relevant.
CoreAccess is a trait extending Actor, because I have methods in that trait access the ActorSystem. (I don't know who to retrieve ActorSelection from a trait without it extending an actor)
Then I create a test Specification
import MyService
import org.specs2.mutable.Specification
import spray.testkit.Specs2RouteTest
import spray.http.StatusCodes._
class RegistrationRouteSpecification extends Specification with Specs2RouteTest with MyService {
def actorRefFactory = system
"The EndPoint " should {
"return Pong to a Get request to the ping" in {
Get("/resources/ping") ~> myRoute ~> check {
status === OK
responseAs[String] === "pong"
}
}
}
}
When I try to execute the test, I get the following compilation error:
[info] Compiling 1 Scala source to /Users/IdeaProjects/endpoint/target/scala-2.10/test-classes...
[error] /Users/IdeaProjects/endpoint/src/test/scala/RegistrationRouteSpecification.scala:19: could not find implicit value for parameter ta: RegistrationRouteSpecification.this.TildeArrow[spray.routing.RequestContext,Unit]
[error] Get("/resources/ping") ~> myRoute ~> check {
[error] ^
[error] one error found
I answer my own question.
I corrected my Build.scala to use the following lines:
val scalaCheck = "org.scalacheck" %% "scalacheck" % Versions.scalaCheckVersion % "test"
val scalaTest = "org.scalatest" %% "scalatest" % "2.2.0" % "test"
Instead of using a simple '%' and supplying a dedicated version.