Skip to content

Commit

Permalink
refactor: move code from using akka to pekko
Browse files Browse the repository at this point in the history
  • Loading branch information
mpujari authored and ane committed Apr 15, 2024
1 parent d7bddea commit bf45267
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 130 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ or see https://github.com/Doikor/jsonapi-scala-example
There is a very generic JsonApiClient interface for implementing a simple client
interface for handling the http query writing side of this

The subproject "akka-client" has an implementation of this using akka-http
The subproject "pekko-client" has an implementation of this using pekko-http

The subproject "http4s-client" has an implementation of this using http4s

Expand Down Expand Up @@ -74,19 +74,19 @@ val filtered = jac.filter[BillingAccount]("some nice filter string here")

### Setup

#### akka-http client
#### pekko-http client
```scala
// needs ActorSystem and Materializer for akka-http
// needs ActorSystem and Materializer for pekko-http
// the ApiEndPoint is used to as the "root" where to launch queries
import io.lemonlabs.uri.typesafe.dsl._
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.stream.Materializer
import com.qvantel.jsonapi.ApiEndpoint
import com.qvantel.jsonapi.JsonApiClient
import com.qvantel.jsonapi.client.akka.AkkaClient._
import com.qvantel.jsonapi.client.pekko.PekkoClient._

implicit val system: ActorSystem = ActorSystem()
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val materializer: Materializer = Materializer(system)
implicit val endpoint: ApiEndpoint = ApiEndpoint.Static("http://localhost:8080/api")

val jac = JsonApiClient.instance
Expand Down
45 changes: 24 additions & 21 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import Dependencies.*

val scala213 = Seq(
"-deprecation", // Emit warning and location for usages of deprecated APIs.
"-encoding",
Expand Down Expand Up @@ -220,15 +222,12 @@ lazy val model = (project in file("model"))
libraryDependencies ++= testDeps
)

val akkaVersion = "2.6.20"
val akkaHttpVersion = "10.2.10"

lazy val akkaClient = (project in file("akka-client"))
lazy val pekkoClient = (project in file("pekko-client"))
.dependsOn(core)
.enablePlugins(MacrosCompiler)
.settings(scalafixSettings)
.settings(
name := "jsonapi-scala-akka-client",
name := "jsonapi-scala-pekko-client",
scalaVersion := scalaVersion213,
crossScalaVersions := Seq(scalaVersion212, scalaVersion213),
scalacOptions ++= {
Expand All @@ -238,19 +237,21 @@ lazy val akkaClient = (project in file("akka-client"))
scala213
},
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-stream" % akkaVersion % Provided,
"com.typesafe.akka" %% "akka-actor" % akkaVersion % Provided,
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion % Provided,
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion % Provided
`pekko-stream` % Provided,
`pekko-actor` % Provided,
`pekko-http` % Provided,
`pekko-http-spray-json` % Provided,
"io.lemonlabs" %% "scala-uri" % "4.0.3" % Test,
"org.parboiled" %% "parboiled" % "2.5.1" % Test
) ++ testDeps
)

lazy val akka = (project in file("akka"))
lazy val pekko = (project in file("pekko"))
.dependsOn(core, model)
.enablePlugins(MacrosCompiler)
.settings(scalafixSettings)
.settings(
name := "jsonapi-scala-akka",
name := "jsonapi-scala-pekko",
scalaVersion := scalaVersion213,
crossScalaVersions := Seq(scalaVersion212, scalaVersion213),
scalacOptions ++= {
Expand All @@ -260,16 +261,18 @@ lazy val akka = (project in file("akka"))
scala213
},
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion % Provided excludeAll (
ExclusionRule(organization = "com.typesafe.akka", name = "akka-cluster"),
ExclusionRule(organization = "com.typesafe.akka", name = "akka-remote")
`pekko-actor` % Provided excludeAll (
ExclusionRule(organization = "org.apache.pekko", name = "pekko-cluster"),
ExclusionRule(organization = "org.apache.pekko", name = "pekko-remote")
),
"com.typesafe.akka" %% "akka-stream" % akkaVersion % Provided,
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion % Provided,
"com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion % Provided,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,
"org.scalatest" %% "scalatest" % "3.2.14" % Test
`pekko-stream` % Provided,
`pekko-http` % Provided,
`pekko-http-core` % Provided,
`pekko-http-testkit` % Test,
`pekko-testkit` % Test,
"io.lemonlabs" %% "scala-uri" % "4.0.3" % Test,
"org.parboiled" %% "parboiled" % "2.5.1" % Test,
"org.scalatest" %% "scalatest" % "3.2.18" % Test
) ++ testDeps
)

Expand Down Expand Up @@ -298,7 +301,7 @@ lazy val http4sClient = (project in file("http4s-client"))
)

lazy val root = (project in file("."))
.aggregate(core, model, akkaClient, http4sClient, akka)
.aggregate(core, model, pekkoClient, http4sClient, pekko)
.settings(
publishArtifact := false,
name := "jsonapi-scala",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package com.qvantel.jsonapi.client.akka
package com.qvantel.jsonapi.client.pekko

import _root_.spray.json._
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.coding.{Deflate, Gzip, NoCoding}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.HttpEncodings
import akka.http.scaladsl.unmarshalling.Unmarshaller._
import akka.http.scaladsl.unmarshalling._
import akka.stream.ActorMaterializer
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.coding.{Deflate, Gzip, NoCoding}
import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.apache.pekko.http.scaladsl.model._
import org.apache.pekko.http.scaladsl.model.headers.HttpEncodings
import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshaller._
import org.apache.pekko.http.scaladsl.unmarshalling._
import org.apache.pekko.stream.Materializer
import cats.effect.{ContextShift, IO}
import io.lemonlabs.uri.Url
import io.lemonlabs.uri.typesafe.dsl._

import com.qvantel.jsonapi._

object AkkaClient {
implicit def instance(implicit m: ActorMaterializer, system: ActorSystem, endpoint: ApiEndpoint): JsonApiClient = {
object PekkoClient {
implicit def instance(implicit m: Materializer, system: ActorSystem, endpoint: ApiEndpoint): JsonApiClient = {
import system.dispatcher
implicit val cs: ContextShift[IO] = IO.contextShift(system.dispatcher)

Expand Down Expand Up @@ -186,7 +186,7 @@ object AkkaClient {
reqUrl: String,
method: HttpMethod = HttpMethods.GET,
entity: RequestEntity = HttpEntity.Empty,
headers: List[HttpHeader])(implicit m: ActorMaterializer, system: ActorSystem): IO[HttpResponse] = {
headers: List[HttpHeader])(implicit m: Materializer, system: ActorSystem): IO[HttpResponse] = {
import system.dispatcher
implicit val cs: ContextShift[IO] = IO.contextShift(system.dispatcher)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
package com.qvantel.jsonapi.client.akka
package com.qvantel.jsonapi.client.pekko

import scala.language.experimental.macros

import scala.concurrent.Await
import scala.concurrent.duration.Duration
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.stream.Materializer
import cats.syntax.traverse._
import cats.data.OptionT
import cats.instances.list._
import io.lemonlabs.uri.typesafe.dsl._
import org.specs2.matcher.MatcherMacros
import org.specs2.mutable.Specification
import org.specs2.specification.AfterAll

import com.qvantel.jsonapi._
import com.qvantel.jsonapi.client.akka.AkkaClient._
import PekkoClient._

class AkkaClientSpec extends Specification with MatcherMacros with AfterAll {
class PekkoClientSpec extends Specification with MatcherMacros with AfterAll {
// this is an integration test.
// to run these tests uncomment this and start a jsonapi.org compatible server in the url specified for the endpoint
skipAll

implicit val system: ActorSystem = ActorSystem()
implicit val m: ActorMaterializer = ActorMaterializer()
implicit val m: Materializer = Materializer(system)
implicit val endpoint: ApiEndpoint = ApiEndpoint.Static("http://localhost:8080/api", Map())

val jac = JsonApiClient.instance
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.qvantel.jsonapi.client.akka
package com.qvantel.jsonapi.client.pekko

import com.qvantel.jsonapi.{ToMany, ToOne, jsonApiResource}
import spray.json.DefaultJsonProtocol._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import com.qvantel.jsonapi.ApiRoot
/**
* Created by ahuttunen on 27/04/2017.
*/
package object akka {
package object pekko {
implicit val apiroot: ApiRoot = ApiRoot.empty
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.qvantel.jsonapi.akka

import _root_.akka.http.scaladsl.Http
import _root_.akka.http.scaladsl.client.RequestBuilding
import _root_.akka.http.scaladsl.marshalling._
import _root_.akka.http.scaladsl.model._
import _root_.akka.http.scaladsl.model.headers._
import _root_.akka.http.scaladsl.unmarshalling._
import _root_.akka.stream.Materializer
import _root_.akka.stream.scaladsl._
import _root_.akka.util.{ByteString, Timeout}
package com.qvantel.jsonapi.pekko

import _root_.org.apache.pekko.http.scaladsl.Http
import _root_.org.apache.pekko.http.scaladsl.client.RequestBuilding
import _root_.org.apache.pekko.http.scaladsl.marshalling._
import _root_.org.apache.pekko.http.scaladsl.model._
import _root_.org.apache.pekko.http.scaladsl.model.headers._
import _root_.org.apache.pekko.http.scaladsl.unmarshalling._
import _root_.org.apache.pekko.stream.Materializer
import _root_.org.apache.pekko.stream.scaladsl._
import _root_.org.apache.pekko.util.{ByteString, Timeout}
import _root_.spray.json._

import scala.concurrent.{ExecutionContext, Future}
Expand Down Expand Up @@ -168,9 +168,9 @@ trait JsonApiSupport0 {
/** Custom SendReceive that adds the include params into X-Internal-Include
* header that can be read by FromResponseUnmarshaller
*/
object JsonApiClientAkka extends RequestBuilding {
import _root_.akka.actor._
import _root_.akka.http.scaladsl.settings.{ClientConnectionSettings, ConnectionPoolSettings}
object JsonApiClientPekko extends RequestBuilding {
import _root_.org.apache.pekko.actor._
import _root_.org.apache.pekko.http.scaladsl.settings.{ClientConnectionSettings, ConnectionPoolSettings}

import scala.concurrent.duration._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,26 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.qvantel.jsonapi.akka

import com.qvantel.jsonapi.model.ErrorObject
package com.qvantel.jsonapi.pekko

import _root_.spray.json.DefaultJsonProtocol._
import _root_.spray.json._

import akka.event.LoggingAdapter
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.{StatusCode, IllegalRequestException, ContentType}
import akka.http.scaladsl.settings.RoutingSettings
import akka.http.scaladsl.model.{HttpEntity, HttpResponse, MediaTypes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.AuthenticationFailedRejection._
import com.qvantel.jsonapi.model.ErrorObject
import org.apache.pekko.event.LoggingAdapter
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.model._
import org.apache.pekko.http.scaladsl.server.AuthenticationFailedRejection._
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.server._
import org.apache.pekko.http.scaladsl.settings.RoutingSettings

import scala.util.control.NonFatal

trait AkkaExceptionHandlerTrait {
trait PekkoExceptionHandlerTrait {

import AkkaExceptionHandlerObject._
import PekkoExceptionHandlerObject._

val defaultAkkaRejectionHandler: RejectionHandler = RejectionHandler
val defaultPekkoRejectionHandler: RejectionHandler = RejectionHandler
.newBuilder()
.handle {
case AuthenticationFailedRejection(cause, _) =>
Expand Down Expand Up @@ -146,27 +143,25 @@ trait AkkaExceptionHandlerTrait {
}
.result()

def defaultAkkaExceptionHandler(implicit settings: RoutingSettings, log: LoggingAdapter): ExceptionHandler =
def defaultPekkoExceptionHandler(implicit settings: RoutingSettings, log: LoggingAdapter): ExceptionHandler =
ExceptionHandler {
case e: IllegalRequestException => {
case e: IllegalRequestException =>
extractRequestContext { ctx =>
log.warning("Illegal request {}\n\t{}\n\tCompleting with '{}' response", ctx.request, e.getMessage, e.status)
complete(jsonApiErrorResponse(e.status, "Illegal Request", e.info.format(settings.verboseErrorMessages)))
}
}
case NonFatal(e) => {
case NonFatal(e) =>
extractRequestContext { ctx =>
log.error(e, "Error during processing of request {}", ctx.request)
complete(
jsonApiErrorResponse(InternalServerError,
InternalServerError.reason,
if (e.getMessage != null) e.getMessage else InternalServerError.defaultMessage))
}
}
}
}

object AkkaExceptionHandlerObject extends Rejection {
object PekkoExceptionHandlerObject extends Rejection {

def jsonApiError(code: StatusCode, title: String, detail: String): JsValue =
JsObject("errors" -> List(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.qvantel.jsonapi

import akka.JsonApiSupport._

import org.specs2.mutable._
import pekko.JsonApiSupport._
import _root_.org.apache.pekko.http.scaladsl.testkit.Specs2RouteTest
import _root_.spray.json.DefaultJsonProtocol._
import _root_.spray.json._
import _root_.akka.http.scaladsl.testkit.Specs2RouteTest
import io.lemonlabs.uri.typesafe.dsl._
import org.apache.pekko.actor.ActorSystem
import org.specs2.mutable._

final class JsonApiSortingAkkaSpec extends Specification with Specs2RouteTest {
def actorRefFactory = system
final class JsonApiSortingPekkoSpec extends Specification with Specs2RouteTest {
def actorRefFactory: ActorSystem = system

implicit val apiRoot: com.qvantel.jsonapi.ApiRoot = ApiRoot(Some("/api"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.qvantel.jsonapi

import com.qvantel.jsonapi.akka.JsonApiSupport._

import pekko.JsonApiSupport._
import org.specs2.mutable._
import _root_.org.apache.pekko.http.scaladsl.model._
import _root_.org.apache.pekko.http.scaladsl.server.Directives._
import _root_.org.apache.pekko.http.scaladsl.testkit.Specs2RouteTest
import _root_.spray.json._
import _root_.spray.json.DefaultJsonProtocol._
import _root_.akka.http.scaladsl.testkit.Specs2RouteTest
import _root_.akka.http.scaladsl.model._
import _root_.akka.http.scaladsl.server.Directives._
import org.apache.pekko.actor.ActorSystem
import org.specs2.mutable._
import spray.json._
import DefaultJsonProtocol._

class RelatedResponseAkkaSpec extends Specification with Specs2RouteTest {
def actorRefFactory = system
class RelatedResponsePekkoSpec extends Specification with Specs2RouteTest {
def actorRefFactory: ActorSystem = system
implicit val apiRoot: com.qvantel.jsonapi.ApiRoot = ApiRoot(None)
@jsonApiResource final case class Test(id: String, name: String)

Expand Down
Loading

0 comments on commit bf45267

Please sign in to comment.