├── .gitignore ├── .scalafmt.conf ├── .travis.yml ├── LICENSE ├── README.md ├── activator.properties ├── build.sbt ├── project ├── build.properties └── plugins.sbt ├── scalastyle-config.xml ├── sonatype.sbt ├── src ├── it │ ├── resources │ │ └── .gitkeep │ └── scala │ │ └── io │ │ └── github │ │ └── yeghishe │ │ └── .gitkeep ├── main │ ├── resources │ │ └── application.conf │ └── scala │ │ └── io │ │ └── github │ │ └── yeghishe │ │ ├── Config.scala │ │ ├── Main.scala │ │ ├── StatusService.scala │ │ └── package.scala └── test │ ├── resources │ └── application.conf │ └── scala │ └── io │ └── github │ └── yeghishe │ ├── ServiceTestBase.scala │ └── StatusServiceTest.scala └── tutorial └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .ensime* 3 | target/ 4 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | style = defaultWithAlign 2 | maxColumn = 120 3 | align.openParenCallSite = false 4 | align.openParenDefnSite = false 5 | danglingParentheses = true 6 | 7 | rewrite.rules = [RedundantBraces, RedundantParens, SortImports, PreferCurlyFors] 8 | rewrite.redundantBraces.includeUnitMethods = true 9 | rewrite.redundantBraces.stringInterpolation = true 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | jdk: 3 | - oraclejdk8 4 | scala: 5 | - 2.12.1 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 (the "License"); 2 | you may not use this file except in compliance with the License. 3 | You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | minimal-scala-akka-http-seed 2 | ========================= 3 | 4 | **Deprecated in favor of [yeghishe/minimal-scala-akka-http-seed.g8](https://github.com/yeghishe/minimal-scala-akka-http-seed.g8)** 5 | 6 | [![Build Status][build-status-badge]][build-status-url] 7 | [![Code Quality][code-quality-badge]][code-quality-url] 8 | 9 | [![Issues][issues-badge]][issues-url] 10 | 11 | [![License][license-badge]][license-url] 12 | [![Chat][chat-badge]][chat-url] 13 | 14 | ## To create a new project run 15 | 16 | ``` 17 | activator new minimal-scala-akka-http-seed 18 | ``` 19 | 20 | ## Overview 21 | The project is intended to be used as an activator template to generate akka http projects. 22 | From the command line, you can execute `activator new minimal-scala-akka-http-seed` to generate a project. From activator UI find the template named `minimal-scala-akka-http-seed` and generate your project using it. 23 | 24 | Once the project is generated you get few things out of the box: 25 | * Most of the wiring is done in [Main](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/main/scala/io/github/yeghishe/Main.scala) file. Create new endpoints and add them to [this map](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/main/scala/io/github/yeghishe/Main.scala#L23), it will do the rest of wiring for you (status "path" in the map will become `/v1/status` endpoint). Think of those key-value mappings as /status is the prefix for all status routes, and there is a base prefix /v1. 26 | * [Config](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/main/scala/io/github/yeghishe/Config.scala) is handled using [Ficus](https://github.com/ceedubs/ficus). Make sure to create your case classes for new config values you add in typesafe config. You can later mix in `Config` trait or import your values from `Config` object. 27 | * [Circe](https://github.com/circe/circe) for json encoding and decoding. 28 | * The project comes with [Cats](http://typelevel.org/cats/) library also. 29 | * [StatusService](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/main/scala/io/github/yeghishe/StatusService.scala) which is more of a health check endpoint but the real goal is to act as a demo service. You'll be spending most of your time creating services and wiring those in Main file. 30 | * [package](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/main/scala/io/github/yeghishe/package.scala) objects contains base classes so you don't have to repeat yourself for every service you create. 31 | * The project uses [ScalaTest](http://www.scalatest.org/) for unit testing. Extend from [ServiceTestBase](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/test/scala/io/github/yeghishe/ServiceTestBase.scala) for your route tests. See [StatusServiceTest](https://github.com/yeghishe/minimal-scala-akka-http-seed/blob/master/src/test/scala/io/github/yeghishe/StatusServiceTest.scala) as an example. 32 | * [Scalafmt](https://github.com/olafurpg/scalafmt) is being used for code formatting. 33 | * [Scalastyle](http://www.scalastyle.org/) is being used fro code style checking. 34 | * [Scoverage](https://github.com/scoverage/sbt-scoverage) is being used for code coverage . 35 | * [Sbt Revolve](https://github.com/spray/sbt-revolver) is being used for local development. 36 | * [Sbt native packager](https://github.com/sbt/sbt-native-packager) is being used for packaging and deployment. 37 | 38 | 39 | [build-status-badge]: https://img.shields.io/travis/yeghishe/minimal-scala-akka-http-seed.svg?style=flat-square 40 | [build-status-url]: https://travis-ci.org/yeghishe/minimal-scala-akka-http-seed 41 | [code-quality-badge]: https://img.shields.io/codacy/5a804d74bb8c4fc28117b0913f17bdd5.svg?style=flat-square 42 | [code-quality-url]: https://www.codacy.com/app/ypiruzyan/minimal-scala-akka-http-seed 43 | [issues-badge]: https://img.shields.io/github/issues/yeghishe/minimal-scala-akka-http-seed.svg?style=flat-square 44 | [issues-url]: https://github.com/yeghishe/minimal-scala-akka-http-seed/issues 45 | [license-badge]: https://img.shields.io/badge/License-Apache%202-blue.svg?style=flat-square 46 | [license-url]: LICENSE 47 | [chat-badge]: https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg?style=flat-square 48 | [chat-url]: https://gitter.im/yeghishe/minimal-scala-akka-http-seed 49 | -------------------------------------------------------------------------------- /activator.properties: -------------------------------------------------------------------------------- 1 | name=minimal-scala-akka-http-seed 2 | title=Minimal Scala Akka Http Seed 3 | description=This is a seed project to create basic akka http projects. It doesn't include a tutorial or demonstration, it's just a minimal project to start your own application from. 4 | tags=scala,akka,akka-http,microservice,seed 5 | authorName=Yeghishe Piruzyan 6 | authorLink=http://yeghishe.github.io/ 7 | authorTwitter=ypiruzyan 8 | authorLogo=https://avatars2.githubusercontent.com/u/1479173 9 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | name := "minimal-scala-akka-http-seed" 2 | organization := "io.github.yeghishe" 3 | version := "0.0.1" 4 | scalaVersion := "2.12.1" 5 | scalacOptions := Seq("-unchecked", "-feature", "-deprecation", "-encoding", "utf8") 6 | 7 | resolvers += Resolver.jcenterRepo 8 | 9 | libraryDependencies ++= { 10 | val catsV = "0.9.0" 11 | val akkaHttpV = "10.0.5" 12 | val circeV = "0.7.0" 13 | val ficusV = "1.4.0" 14 | val scalaMockV = "3.5.0" 15 | val catsScalatestV = "2.2.0" 16 | 17 | Seq( 18 | "org.typelevel" %% "cats-core" % catsV, 19 | "com.iheart" %% "ficus" % ficusV, 20 | "com.typesafe.akka" %% "akka-http" % akkaHttpV, 21 | "de.heikoseeberger" %% "akka-http-circe" % "1.15.0", 22 | "io.circe" %% "circe-core" % circeV, 23 | "io.circe" %% "circe-generic" % circeV, 24 | "io.circe" %% "circe-parser" % circeV, 25 | "org.scalamock" %% "scalamock-scalatest-support" % scalaMockV % "it,test", 26 | "com.ironcorelabs" %% "cats-scalatest" % catsScalatestV % "it,test", 27 | "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpV % "it,test" 28 | ) 29 | } 30 | 31 | lazy val root = project.in(file(".")).configs(IntegrationTest) 32 | Defaults.itSettings 33 | Revolver.settings 34 | enablePlugins(JavaAppPackaging) 35 | 36 | 37 | initialCommands := """ 38 | import cats._ 39 | import cats.data._ 40 | import cats.implicits._ 41 | import akka.actor._ 42 | import akka.pattern._ 43 | import akka.util._ 44 | import scala.concurrent._ 45 | import scala.concurrent.duration._ 46 | """.stripMargin 47 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.13 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | resolvers += Classpaths.sbtPluginReleases 2 | 3 | addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.5.5") 4 | addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0") 5 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.0") 6 | addSbtPlugin("io.spray" %% "sbt-revolver" % "0.8.0") 7 | addSbtPlugin("com.typesafe.sbt" %% "sbt-native-packager" % "1.2.0-M8") 8 | -------------------------------------------------------------------------------- /scalastyle-config.xml: -------------------------------------------------------------------------------- 1 | 2 | Scalastyle standard configuration 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /sonatype.sbt: -------------------------------------------------------------------------------- 1 | pomExtra in Global := { 2 | http://yeghishe.github.io/NAME 3 | 4 | 5 | Apache 2 6 | http://www.apache.org/licenses/LICENSE-2.0.txt 7 | repo 8 | 9 | 10 | 11 | scm:git:github.com:yeghishe/NAME 12 | scm:git:git@github.com:yeghishe/NAME.git 13 | https://github.com/yeghishe/NAME 14 | 15 | 16 | 17 | ypiruzyan 18 | Yeghishe Piruzyan 19 | https://yeghishe.github.io 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/it/resources/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yeghishe/minimal-scala-akka-http-seed/5ccc6660774b66411b213b2a7849beae7d26ec13/src/it/resources/.gitkeep -------------------------------------------------------------------------------- /src/it/scala/io/github/yeghishe/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yeghishe/minimal-scala-akka-http-seed/5ccc6660774b66411b213b2a7849beae7d26ec13/src/it/scala/io/github/yeghishe/.gitkeep -------------------------------------------------------------------------------- /src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = DEBUG 3 | } 4 | 5 | http { 6 | interface = "0.0.0.0" 7 | port = 9000 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/io/github/yeghishe/Config.scala: -------------------------------------------------------------------------------- 1 | package io.github.yeghishe 2 | 3 | import com.typesafe.config.ConfigFactory 4 | import net.ceedubs.ficus.Ficus 5 | import net.ceedubs.ficus.readers.ArbitraryTypeReader 6 | import net.ceedubs.ficus.readers.namemappers.implicits 7 | 8 | trait Config { 9 | import Ficus._ 10 | import ArbitraryTypeReader._ 11 | import implicits.hyphenCase 12 | 13 | protected case class HttpConfig(interface: String, port: Int) 14 | 15 | private val config = ConfigFactory.load() 16 | protected val httpConfig: HttpConfig = config.as[HttpConfig]("http") 17 | } 18 | 19 | object Config extends Config 20 | -------------------------------------------------------------------------------- /src/main/scala/io/github/yeghishe/Main.scala: -------------------------------------------------------------------------------- 1 | package io.github.yeghishe 2 | 3 | import akka.actor.ActorSystem 4 | import akka.event.Logging 5 | import akka.http.scaladsl.Http 6 | import akka.http.scaladsl.server.{Directives, Route} 7 | import akka.stream.ActorMaterializer 8 | 9 | object Main extends App with Config with Services { 10 | implicit val system = ActorSystem() 11 | implicit val materializer = ActorMaterializer() 12 | 13 | override protected def log = Logging(system, "service") 14 | override protected def executor = system.dispatcher 15 | 16 | Http().bindAndHandle(routes, httpConfig.interface, httpConfig.port) 17 | } 18 | 19 | trait Services extends StatusService { 20 | import Directives._ 21 | 22 | private val apiVersion = "v1" 23 | private val allRoutes = Map( 24 | "status" -> super[StatusService].routes 25 | ) 26 | 27 | protected override val routes: Route = pathPrefix(apiVersion) { 28 | allRoutes.map { 29 | case (k, v) => path(k)(v) 30 | } reduce (_ ~ _) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/io/github/yeghishe/StatusService.scala: -------------------------------------------------------------------------------- 1 | package io.github.yeghishe 2 | 3 | import java.lang.management.ManagementFactory 4 | import akka.http.scaladsl.server.{Directives, Route} 5 | import scala.concurrent.duration._ 6 | 7 | trait StatusService extends BaseService { 8 | import Directives._ 9 | import io.circe.generic.auto._ 10 | 11 | protected case class Status(uptime: String) 12 | 13 | override protected def routes: Route = 14 | get { 15 | log.info("/status executed") 16 | complete(Status(Duration(ManagementFactory.getRuntimeMXBean.getUptime, MILLISECONDS).toString())) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/io/github/yeghishe/package.scala: -------------------------------------------------------------------------------- 1 | package io.github 2 | 3 | import akka.event.LoggingAdapter 4 | import akka.http.scaladsl.server.Route 5 | import de.heikoseeberger.akkahttpcirce.CirceSupport 6 | 7 | import scala.concurrent.ExecutionContext 8 | 9 | package object yeghishe { 10 | trait BaseComponent extends Config { 11 | protected implicit def log: LoggingAdapter 12 | protected implicit def executor: ExecutionContext 13 | } 14 | 15 | trait BaseService extends BaseComponent with CirceSupport { 16 | protected def routes: Route 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = WARNING 3 | } 4 | -------------------------------------------------------------------------------- /src/test/scala/io/github/yeghishe/ServiceTestBase.scala: -------------------------------------------------------------------------------- 1 | package io.github.yeghishe 2 | 3 | import akka.event.{LoggingAdapter, NoLogging} 4 | import akka.http.scaladsl.testkit.ScalatestRouteTest 5 | import org.scalamock.scalatest.MockFactory 6 | import org.scalatest.{Matchers, WordSpec} 7 | 8 | trait ServiceTestBase extends WordSpec with Matchers with ScalatestRouteTest with MockFactory { 9 | protected def log: LoggingAdapter = NoLogging 10 | } 11 | -------------------------------------------------------------------------------- /src/test/scala/io/github/yeghishe/StatusServiceTest.scala: -------------------------------------------------------------------------------- 1 | package io.github.yeghishe 2 | 3 | import akka.http.scaladsl.model.StatusCodes 4 | 5 | class StatusServiceTest extends ServiceTestBase with StatusService { 6 | import io.circe.generic.auto._ 7 | 8 | "StatusService" when { 9 | "GET /status" should { 10 | "return time" in { 11 | Get("/status") ~> routes ~> check { 12 | status should be(StatusCodes.OK) 13 | responseAs[Status].uptime should include("milliseconds") 14 | } 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tutorial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Minimal Scala Akka Seed - Activator Template 4 | 5 | 6 |
7 |

Edit build.sbt to set up your own app

8 | 9 |

10 | build.sbt contains the build configuration; you'll 12 | want to change the project name, organization and version, to start. 13 |

14 | 15 |

16 | Many templates contain tutorials but this seed template is just intended 17 | as a starting point for creating a new app. 18 |

19 |
20 | 21 | 22 | --------------------------------------------------------------------------------