[scala][akka] Update dependencies for scala 2.13 in scala-akka (#8624)

* [scala][akka] Update dependencies for scala 2.13

* Update pom.mustache to support multiple scala's version

* Update pom.xml

* Scala cross build 2.12 and 2.13

* Update version. Migrate to sbt

* Remove space

* Add pom.xml back
This commit is contained in:
ex0ns 2021-04-29 12:51:30 +02:00 committed by GitHub
parent dbb42f9027
commit ebc1d7bd95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 143 additions and 91 deletions

View File

@ -166,8 +166,8 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf")); supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf"));
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator); final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala")); supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala"));
@ -175,6 +175,7 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala")); supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala"));
supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala")); supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala"));
final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator); final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("project/build.properties.mustache", "project", "build.properties"));
supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala")); supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala"));
supportingFiles.add(new SupportingFile("serializers.mustache", invokerFolder, "Serializers.scala")); supportingFiles.add(new SupportingFile("serializers.mustache", invokerFolder, "Serializers.scala"));
} }

View File

@ -18,6 +18,7 @@ import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import org.json4s._ import org.json4s._
import org.json4s.jackson.JsonMethods._ import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization import org.json4s.jackson.Serialization
import scala.collection.compat._
import scala.collection.immutable import scala.collection.immutable
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future } import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future }
@ -86,7 +87,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private val http = Http() private val http = Http()
val CompressionFilter: HttpMessage Boolean = (msg: HttpMessage) => val CompressionFilter: HttpMessage => Boolean = (msg: HttpMessage) =>
Seq( Seq(
{ _: HttpMessage => settings.compressionEnabled }, { _: HttpMessage => settings.compressionEnabled },
Encoder.DefaultFilter, Encoder.DefaultFilter,
@ -115,7 +116,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] = private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] =
headers.asFormattedParams headers.asFormattedParams
.map { case (name, value) => RawHeader(name, value.toString) } .map { case (name, value) => RawHeader(name, value.toString) }
.to[immutable.Seq] .to(immutable.Seq)
private def bodyPart(name: String, value: Any): BodyPart = { private def bodyPart(name: String, value: Any): BodyPart = {
@ -147,9 +148,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
case MediaTypes.`multipart/form-data` => case MediaTypes.`multipart/form-data` =>
Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) })) Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) }))
case MediaTypes.`application/x-www-form-urlencoded` => case MediaTypes.`application/x-www-form-urlencoded` =>
FormData(params.mapValues(_.toString)) FormData(params.view.mapValues(_.toString).toMap)
case _: MediaType => // Default : application/x-www-form-urlencoded. case _: MediaType => // Default : application/x-www-form-urlencoded.
FormData(params.mapValues(_.toString)) FormData(params.view.mapValues(_.toString).toMap)
} }
) )
} }
@ -187,7 +188,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
params + (keyName -> key.value) params + (keyName -> key.value)
case (params, _) => params case (params, _) => params
}.asFormattedParams }.asFormattedParams
.view
.mapValues(_.toString) .mapValues(_.toString)
.toMap
.foldRight[Query](Uri.Query.Empty) { .foldRight[Query](Uri.Query.Empty) {
case ((name, value), acc) => acc.+:(name, value) case ((name, value), acc) => acc.+:(name, value)
} }
@ -196,7 +199,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
def makeUri(r: ApiRequest[_]): Uri = { def makeUri(r: ApiRequest[_]): Uri = {
val opPath = r.operationPath.replaceAll("\\{format\\}", "json") val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
val opPathWithParams = r.pathParams.asFormattedParams val opPathWithParams = r.pathParams.asFormattedParams
.view
.mapValues(_.toString) .mapValues(_.toString)
.toMap
.foldLeft(opPath) { .foldLeft(opPath) {
case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value) case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
} }
@ -213,13 +218,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
http http
.singleRequest(request) .singleRequest(request)
.map { response => .map { response =>
val decoder: Coder with StreamDecoder = response.encoding match { val decoder: Decoder with Decoder = response.encoding match {
case HttpEncodings.gzip case HttpEncodings.gzip =>
Gzip Coders.Gzip
case HttpEncodings.deflate case HttpEncodings.deflate =>
Deflate Coders.Deflate
case HttpEncodings.identity case HttpEncodings.identity =>
NoCoding Coders.NoCoding
case HttpEncoding(encoding) => case HttpEncoding(encoding) =>
throw new IllegalArgumentException(s"Unsupported encoding: $encoding") throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
} }
@ -247,13 +252,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
request request
.responseForCode(response.status.intValue) match { .responseForCode(response.status.intValue) match {
case Some((Manifest.Unit, state: ResponseState)) => case Some((Manifest.Unit, state: ResponseState)) =>
Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]]) Future(responseForState(state, ()).asInstanceOf[ApiResponse[T]])
case Some((manifest, state: ResponseState)) if manifest == mf => case Some((manifest, state: ResponseState)) if manifest == mf =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats) implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
Unmarshal(response.entity) Unmarshal(response.entity)
.to[T] .to[T]
.recoverWith { .recoverWith {
case e throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e) case e => throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
} }
.map(value => responseForState(state, value)) .map(value => responseForState(state, value))
case None | Some(_) => case None | Some(_) =>

View File

@ -3,12 +3,12 @@ package {{invokerPackage}}
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import akka.actor.{ ExtendedActorSystem, Extension, ExtensionKey } import akka.actor.{ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import akka.http.scaladsl.model.StatusCodes.CustomStatusCode import akka.http.scaladsl.model.StatusCodes.CustomStatusCode
import akka.http.scaladsl.model.headers.RawHeader import akka.http.scaladsl.model.headers.RawHeader
import com.typesafe.config.Config import com.typesafe.config.Config
import scala.collection.JavaConverters._ import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration import scala.concurrent.duration.FiniteDuration
class ApiSettings(config: Config) extends Extension { class ApiSettings(config: Config) extends Extension {
@ -32,4 +32,13 @@ class ApiSettings(config: Config) extends Extension {
} }
} }
object ApiSettings extends ExtensionKey[ApiSettings] object ApiSettings extends ExtensionId[ApiSettings] with ExtensionIdProvider {
override def lookup = ApiSettings
override def createExtension(system: ExtendedActorSystem): ApiSettings =
new ApiSettings(system)
// needed to get the type right when used from Java
override def get(system: ActorSystem): ApiSettings = super.get(system)
}

View File

@ -1,22 +1,26 @@
version := "{{artifactVersion}}" version := "{{artifactVersion}}"
name := "{{artifactId}}" name := "{{artifactId}}"
organization := "{{groupId}}" organization := "{{groupId}}"
scalaVersion := "2.12.8"
scalaVersion := "2.12.13"
crossScalaVersions := Seq(scalaVersion.value, "2.13.4")
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.3.3", "com.typesafe" % "config" % "1.4.1",
"com.typesafe.akka" %% "akka-actor" % "2.5.21", "com.typesafe.akka" %% "akka-actor" % "2.6.12",
"com.typesafe.akka" %% "akka-stream" % "2.5.21", "com.typesafe.akka" %% "akka-stream" % "2.6.12",
"com.typesafe.akka" %% "akka-http" % "10.1.7", "com.typesafe.akka" %% "akka-http" % "10.2.3",
{{#joda}} {{#joda}}
"joda-time" % "joda-time" % "2.10.1", "joda-time" % "joda-time" % "2.10.1",
{{/joda}} {{/joda}}
"org.json4s" %% "json4s-jackson" % "3.6.5", "org.json4s" %% "json4s-jackson" % "3.6.7",
"org.json4s" %% "json4s-ext" % "3.6.5", "org.json4s" %% "json4s-ext" % "3.6.7",
"de.heikoseeberger" %% "akka-http-json4s" % "1.25.2", "de.heikoseeberger" %% "akka-http-json4s" % "1.27.0",
"org.scala-lang.modules" %% "scala-collection-compat" % "2.4.1",
// test dependencies // test dependencies
"org.scalatest" %% "scalatest" % "3.0.5" % "test", "org.scalatest" %% "scalatest" % "3.2.3" % "test",
"junit" % "junit" % "4.13.1" % "test" "org.scalatestplus" %% "junit-4-13" % "3.2.3.0" % "test"
) )
resolvers ++= Seq(Resolver.mavenLocal) resolvers ++= Seq(Resolver.mavenLocal)

View File

@ -15,18 +15,19 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<scala.version>2.12.8</scala.version> <scala.version>2.12.13</scala.version>
<json4s.jackson.version>3.5.3</json4s.jackson.version> <json4s.jackson.version>3.6.7</json4s.jackson.version>
<json4s.ext.version>3.2.11</json4s.ext.version> <json4s.ext.version>3.6.7</json4s.ext.version>
<akka.version>2.5.21</akka.version> <akka.version>2.6.12</akka.version>
<akka.http.version>10.1.7</akka.http.version> <akka.http.version>10.2.3</akka.http.version>
{{#joda}} {{#joda}}
<joda.time.version>2.10.1</joda.time.version> <joda.time.version>2.10.1</joda.time.version>
{{/joda}} {{/joda}}
<typesafeconfig.version>1.3.3</typesafeconfig.version> <typesafeconfig.version>1.4.1</typesafeconfig.version>
<akka.http.json4s.version>1.25.2</akka.http.json4s.version> <akka.http.json4s.version>1.27.0</akka.http.json4s.version>
<junit.version>4.13.1</junit.version> <scala.compat.version>2.4.1</scala.compat.version>
<scala.test.version>3.0.5</scala.test.version> <scala.test.version>3.2.3</scala.test.version>
<scala.test.plus.version>3.2.3.0</scala.test.plus.version>
<scala.maven.plugin.version>3.3.1</scala.maven.plugin.version> <scala.maven.plugin.version>3.3.1</scala.maven.plugin.version>
</properties> </properties>
@ -80,6 +81,11 @@
<artifactId>akka-http-json4s_2.12</artifactId> <artifactId>akka-http-json4s_2.12</artifactId>
<version>${akka.http.json4s.version}</version> <version>${akka.http.json4s.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-collection-compat_2.12</artifactId>
<version>${scala.compat.version}</version>
</dependency>
<!--test dependencies--> <!--test dependencies-->
<dependency> <dependency>
@ -89,9 +95,9 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.scalatestplus</groupId>
<artifactId>junit</artifactId> <artifactId>junit-4-13_2.12</artifactId>
<version>${junit.version}</version> <version>${scala.test.plus.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1 @@
sbt.version=1.3.10

View File

@ -472,7 +472,7 @@ public class ScalaAkkaClientCodegenTest {
Generator gen = generator.opts(clientOptInput); Generator gen = generator.opts(clientOptInput);
List<File> files = gen.generate(); List<File> files = gen.generate();
Assert.assertEquals(files.size(), 15); Assert.assertEquals(files.size(), 16);
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/SomeObj.scala"); TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/SomeObj.scala");
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/core/ApiSettings.scala"); TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/core/ApiSettings.scala");
@ -509,7 +509,7 @@ public class ScalaAkkaClientCodegenTest {
Generator gen = generator.opts(clientOptInput); Generator gen = generator.opts(clientOptInput);
List<File> files = gen.generate(); List<File> files = gen.generate();
Assert.assertEquals(files.size(), 15); Assert.assertEquals(files.size(), 16);
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/package/SomeObj.scala"); TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/package/SomeObj.scala");
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/package/invoker/ApiSettings.scala"); TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/package/invoker/ApiSettings.scala");

View File

@ -1,5 +1,6 @@
README.md README.md
build.sbt build.sbt
project/build.properties
src/main/resources/reference.conf src/main/resources/reference.conf
src/main/scala/org/openapitools/client/api/EnumsSerializers.scala src/main/scala/org/openapitools/client/api/EnumsSerializers.scala
src/main/scala/org/openapitools/client/api/PetApi.scala src/main/scala/org/openapitools/client/api/PetApi.scala

View File

@ -1,19 +1,23 @@
version := "1.0.0" version := "1.0.0"
name := "scala-akka-petstore-client" name := "scala-akka-petstore-client"
organization := "org.openapitools" organization := "org.openapitools"
scalaVersion := "2.12.8"
scalaVersion := "2.12.13"
crossScalaVersions := Seq(scalaVersion.value, "2.13.4")
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.3.3", "com.typesafe" % "config" % "1.4.1",
"com.typesafe.akka" %% "akka-actor" % "2.5.21", "com.typesafe.akka" %% "akka-actor" % "2.6.12",
"com.typesafe.akka" %% "akka-stream" % "2.5.21", "com.typesafe.akka" %% "akka-stream" % "2.6.12",
"com.typesafe.akka" %% "akka-http" % "10.1.7", "com.typesafe.akka" %% "akka-http" % "10.2.3",
"org.json4s" %% "json4s-jackson" % "3.6.5", "org.json4s" %% "json4s-jackson" % "3.6.7",
"org.json4s" %% "json4s-ext" % "3.6.5", "org.json4s" %% "json4s-ext" % "3.6.7",
"de.heikoseeberger" %% "akka-http-json4s" % "1.25.2", "de.heikoseeberger" %% "akka-http-json4s" % "1.27.0",
"org.scala-lang.modules" %% "scala-collection-compat" % "2.4.1",
// test dependencies // test dependencies
"org.scalatest" %% "scalatest" % "3.0.5" % "test", "org.scalatest" %% "scalatest" % "3.2.3" % "test",
"junit" % "junit" % "4.13.1" % "test" "org.scalatestplus" %% "junit-4-13" % "3.2.3.0" % "test"
) )
resolvers ++= Seq(Resolver.mavenLocal) resolvers ++= Seq(Resolver.mavenLocal)

View File

@ -15,15 +15,16 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<scala.version>2.12.8</scala.version> <scala.version>2.12.13</scala.version>
<json4s.jackson.version>3.5.3</json4s.jackson.version> <json4s.jackson.version>3.6.7</json4s.jackson.version>
<json4s.ext.version>3.2.11</json4s.ext.version> <json4s.ext.version>3.6.7</json4s.ext.version>
<akka.version>2.5.21</akka.version> <akka.version>2.6.12</akka.version>
<akka.http.version>10.1.7</akka.http.version> <akka.http.version>10.2.3</akka.http.version>
<typesafeconfig.version>1.3.3</typesafeconfig.version> <typesafeconfig.version>1.4.1</typesafeconfig.version>
<akka.http.json4s.version>1.25.2</akka.http.json4s.version> <akka.http.json4s.version>1.27.0</akka.http.json4s.version>
<junit.version>4.13</junit.version> <scala.compat.version>2.4.1</scala.compat.version>
<scala.test.version>3.0.5</scala.test.version> <scala.test.version>3.2.3</scala.test.version>
<scala.test.plus.version>3.2.3.0</scala.test.plus.version>
<scala.maven.plugin.version>3.3.1</scala.maven.plugin.version> <scala.maven.plugin.version>3.3.1</scala.maven.plugin.version>
</properties> </properties>
@ -70,6 +71,11 @@
<artifactId>akka-http-json4s_2.12</artifactId> <artifactId>akka-http-json4s_2.12</artifactId>
<version>${akka.http.json4s.version}</version> <version>${akka.http.json4s.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-collection-compat_2.12</artifactId>
<version>${scala.compat.version}</version>
</dependency>
<!--test dependencies--> <!--test dependencies-->
<dependency> <dependency>
@ -79,9 +85,9 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.scalatestplus</groupId>
<artifactId>junit</artifactId> <artifactId>junit-4-13_2.12</artifactId>
<version>${junit.version}</version> <version>${scala.test.plus.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1 @@
sbt.version=1.3.10

View File

@ -28,6 +28,7 @@ import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import org.json4s._ import org.json4s._
import org.json4s.jackson.JsonMethods._ import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization import org.json4s.jackson.Serialization
import scala.collection.compat._
import scala.collection.immutable import scala.collection.immutable
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future } import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future }
@ -96,7 +97,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private val http = Http() private val http = Http()
val CompressionFilter: HttpMessage Boolean = (msg: HttpMessage) => val CompressionFilter: HttpMessage => Boolean = (msg: HttpMessage) =>
Seq( Seq(
{ _: HttpMessage => settings.compressionEnabled }, { _: HttpMessage => settings.compressionEnabled },
Encoder.DefaultFilter, Encoder.DefaultFilter,
@ -125,7 +126,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] = private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] =
headers.asFormattedParams headers.asFormattedParams
.map { case (name, value) => RawHeader(name, value.toString) } .map { case (name, value) => RawHeader(name, value.toString) }
.to[immutable.Seq] .to(immutable.Seq)
private def bodyPart(name: String, value: Any): BodyPart = { private def bodyPart(name: String, value: Any): BodyPart = {
@ -157,9 +158,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
case MediaTypes.`multipart/form-data` => case MediaTypes.`multipart/form-data` =>
Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) })) Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) }))
case MediaTypes.`application/x-www-form-urlencoded` => case MediaTypes.`application/x-www-form-urlencoded` =>
FormData(params.mapValues(_.toString)) FormData(params.view.mapValues(_.toString).toMap)
case _: MediaType => // Default : application/x-www-form-urlencoded. case _: MediaType => // Default : application/x-www-form-urlencoded.
FormData(params.mapValues(_.toString)) FormData(params.view.mapValues(_.toString).toMap)
} }
) )
} }
@ -197,7 +198,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
params + (keyName -> key.value) params + (keyName -> key.value)
case (params, _) => params case (params, _) => params
}.asFormattedParams }.asFormattedParams
.view
.mapValues(_.toString) .mapValues(_.toString)
.toMap
.foldRight[Query](Uri.Query.Empty) { .foldRight[Query](Uri.Query.Empty) {
case ((name, value), acc) => acc.+:(name, value) case ((name, value), acc) => acc.+:(name, value)
} }
@ -206,7 +209,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
def makeUri(r: ApiRequest[_]): Uri = { def makeUri(r: ApiRequest[_]): Uri = {
val opPath = r.operationPath.replaceAll("\\{format\\}", "json") val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
val opPathWithParams = r.pathParams.asFormattedParams val opPathWithParams = r.pathParams.asFormattedParams
.view
.mapValues(_.toString) .mapValues(_.toString)
.toMap
.foldLeft(opPath) { .foldLeft(opPath) {
case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value) case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
} }
@ -223,13 +228,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
http http
.singleRequest(request) .singleRequest(request)
.map { response => .map { response =>
val decoder: Coder with StreamDecoder = response.encoding match { val decoder: Decoder with Decoder = response.encoding match {
case HttpEncodings.gzip case HttpEncodings.gzip =>
Gzip Coders.Gzip
case HttpEncodings.deflate case HttpEncodings.deflate =>
Deflate Coders.Deflate
case HttpEncodings.identity case HttpEncodings.identity =>
NoCoding Coders.NoCoding
case HttpEncoding(encoding) => case HttpEncoding(encoding) =>
throw new IllegalArgumentException(s"Unsupported encoding: $encoding") throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
} }
@ -257,13 +262,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
request request
.responseForCode(response.status.intValue) match { .responseForCode(response.status.intValue) match {
case Some((Manifest.Unit, state: ResponseState)) => case Some((Manifest.Unit, state: ResponseState)) =>
Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]]) Future(responseForState(state, ()).asInstanceOf[ApiResponse[T]])
case Some((manifest, state: ResponseState)) if manifest == mf => case Some((manifest, state: ResponseState)) if manifest == mf =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats) implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
Unmarshal(response.entity) Unmarshal(response.entity)
.to[T] .to[T]
.recoverWith { .recoverWith {
case e throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e) case e => throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
} }
.map(value => responseForState(state, value)) .map(value => responseForState(state, value))
case None | Some(_) => case None | Some(_) =>

View File

@ -13,12 +13,12 @@ package org.openapitools.client.core
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import akka.actor.{ ExtendedActorSystem, Extension, ExtensionKey } import akka.actor.{ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import akka.http.scaladsl.model.StatusCodes.CustomStatusCode import akka.http.scaladsl.model.StatusCodes.CustomStatusCode
import akka.http.scaladsl.model.headers.RawHeader import akka.http.scaladsl.model.headers.RawHeader
import com.typesafe.config.Config import com.typesafe.config.Config
import scala.collection.JavaConverters._ import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration import scala.concurrent.duration.FiniteDuration
class ApiSettings(config: Config) extends Extension { class ApiSettings(config: Config) extends Extension {
@ -42,4 +42,13 @@ class ApiSettings(config: Config) extends Extension {
} }
} }
object ApiSettings extends ExtensionKey[ApiSettings] object ApiSettings extends ExtensionId[ApiSettings] with ExtensionIdProvider {
override def lookup = ApiSettings
override def createExtension(system: ExtendedActorSystem): ApiSettings =
new ApiSettings(system)
// needed to get the type right when used from Java
override def get(system: ActorSystem): ApiSettings = super.get(system)
}

View File

@ -5,18 +5,19 @@ import org.openapitools.client.api._
import org.openapitools.client.core.{ApiInvoker, ApiKeyValue} import org.openapitools.client.core.{ApiInvoker, ApiKeyValue}
import org.openapitools.client.model._ import org.openapitools.client.model._
import org.scalatest.Inspectors._ import org.scalatest.Inspectors._
import org.scalatest._ import org.scalatest.flatspec.AsyncFlatSpec
import org.scalatest.junit.JUnitRunner import org.scalatest.matchers.should.Matchers
import org.scalatestplus.junit.JUnitRunner
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class PetApiTest extends AsyncFlatSpec with Matchers { class PetApiTest extends AsyncFlatSpec with Matchers {
private implicit val system: ActorSystem = ActorSystem() implicit private val system: ActorSystem = ActorSystem()
behavior of "PetApi" behavior of "PetApi"
val api: PetApi = PetApi() val api: PetApi = PetApi()
val invoker: ApiInvoker = ApiInvoker(EnumsSerializers.all) val invoker: ApiInvoker = ApiInvoker(EnumsSerializers.all)
private implicit val apiKey: ApiKeyValue = ApiKeyValue("special-key") implicit private val apiKey: ApiKeyValue = ApiKeyValue("special-key")
it should "add and fetch a pet" in { it should "add and fetch a pet" in {
val petId = 1000 val petId = 1000
@ -34,7 +35,7 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
for { for {
addResponse <- invoker.execute(addPetRequest) addResponse <- invoker.execute(addPetRequest)
response <- invoker.execute(getPetRequest) response <- invoker.execute(getPetRequest)
} yield { } yield {
addResponse.code should be(200) addResponse.code should be(200)
@ -54,7 +55,7 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
} }
it should "update a pet" in { it should "update a pet" in {
val petId = (Math.random()*1000000000).toLong val petId = (Math.random() * 1000000000).toLong
val createdPet = Pet( val createdPet = Pet(
Some(petId), Some(petId),
Some(Category(Some(1), Some("sold"))), Some(Category(Some(1), Some("sold"))),
@ -64,12 +65,12 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
Some(PetEnums.Status.Available) Some(PetEnums.Status.Available)
) )
for { for {
createdPet <- invoker.execute(api.addPet(createdPet)) createdPet <- invoker.execute(api.addPet(createdPet))
pet: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get)) pet: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get))
updatedPet = pet.content.copy(status = Some(PetEnums.Status.Sold), name = "developer") updatedPet = pet.content.copy(status = Some(PetEnums.Status.Sold), name = "developer")
updatedPetResponse: core.ApiResponse[Pet] <- invoker.execute(api.updatePet(updatedPet)) updatedPetResponse: core.ApiResponse[Pet] <- invoker.execute(api.updatePet(updatedPet))
updatedRequested: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get)) updatedRequested: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get))
} yield { } yield {
pet.content.name should be("programmer") pet.content.name should be("programmer")
pet.content.status should be(Some(PetEnums.Status.Available)) pet.content.status should be(Some(PetEnums.Status.Available))
@ -120,4 +121,3 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
} }
*/ */
} }