From 1b07da462dbc827e3acf7f19365762f633716f59 Mon Sep 17 00:00:00 2001 From: Chris Birchall Date: Sat, 7 Mar 2015 18:46:15 +0000 Subject: [PATCH] Initial commit --- .gitignore | 1 + project/Build.scala | 87 +++++++++++++++++++ project/build.properties | 1 + project/plugins.sbt | 5 ++ .../plugins/ConfigurableNingWSPlugin.scala | 59 +++++++++++++ src/test/scala/play/plugins/PluginSpec.scala | 27 ++++++ version.sbt | 1 + 7 files changed, 181 insertions(+) create mode 100644 .gitignore create mode 100644 project/Build.scala create mode 100644 project/build.properties create mode 100644 project/plugins.sbt create mode 100644 src/main/scala/play/plugins/ConfigurableNingWSPlugin.scala create mode 100644 src/test/scala/play/plugins/PluginSpec.scala create mode 100644 version.sbt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98d8a5a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +logs diff --git a/project/Build.scala b/project/Build.scala new file mode 100644 index 0000000..5420738 --- /dev/null +++ b/project/Build.scala @@ -0,0 +1,87 @@ +import sbt._ +import Keys._ +import xerial.sbt.Sonatype._ +import SonatypeKeys._ +import com.typesafe.sbt.pgp.PgpKeys +import sbtrelease._ +import sbtrelease.ReleasePlugin._ +import sbtrelease.ReleasePlugin.ReleaseKeys._ +import sbtrelease.ReleaseStateTransformations._ + +import scala.language.postfixOps + +object ConfigurableNingWSPluginBuild extends Build { + + val playVersion = "2.3.8" + + lazy val plugin = Project( + id = "play-configurable-ningwsplugin", + base = file("."), + settings = Seq( + organization := "com.github.cb372", + scalaVersion := "2.11.5", + scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature"), + resolvers += Resolver.typesafeRepo("releases"), + libraryDependencies ++= Seq( + "com.typesafe.play" %% "play-ws" % playVersion % Provided, + "com.typesafe.play" %% "play-test" % playVersion % Test, + "com.typesafe.play" %% "play-test" % playVersion % Test, + "org.scalatestplus" %% "play" % "1.2.0" % Test + ), + publishArtifactsAction := PgpKeys.publishSigned.value, + ReleaseKeys.releaseProcess := Seq[ReleaseStep]( + checkSnapshotDependencies, + inquireVersions, + runClean, + runTest, + setReleaseVersion, + commitReleaseVersion, + tagRelease, + publishArtifacts, + setNextVersion, + commitNextVersion, + pushChanges, + deployToMavenCentral + ) + ) ++ + releaseSettings ++ + mavenSettings + ) + + lazy val mavenSettings = Seq( + pomExtra := + https://github.com/cb372/play-configurable-ningwsplugin + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.html + repo + + + + git@github.com:cb372/play-configurable-ningwsplugin.git + scm:git:git@github.com:cb372/play-configurable-ningwsplugin.git + + + + cb372 + Chris Birchall + https://github.com/cb372 + + , + publishTo <<= version { v => + val nexus = "https://oss.sonatype.org/" + if (v.trim.endsWith("SNAPSHOT")) + Some("snapshots" at nexus + "content/repositories/snapshots") + else + Some("releases" at nexus + "service/local/staging/deploy/maven2") + }, + publishMavenStyle := true, + publishArtifact in Test := false, + pomIncludeRepository := { _ => false } + ) + + lazy val deployToMavenCentral = ReleaseStep(action = releaseTask(sonatypeReleaseAll)) +} + + diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..748703f --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.7 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..e24d760 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1,5 @@ +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.2.1") + +addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1") + +addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5") diff --git a/src/main/scala/play/plugins/ConfigurableNingWSPlugin.scala b/src/main/scala/play/plugins/ConfigurableNingWSPlugin.scala new file mode 100644 index 0000000..3a4735c --- /dev/null +++ b/src/main/scala/play/plugins/ConfigurableNingWSPlugin.scala @@ -0,0 +1,59 @@ +package play.plugins + +import com.ning.http.client.AsyncHttpClientConfig +import play.api.{Configuration, Application} +import play.api.libs.ws.ning.{NingAsyncHttpClientConfigBuilder, NingWSAPI} +import play.api.libs.ws.{WSClientConfig, DefaultWSConfigParser, WSPlugin} + +/** + * A modified version of play.api.libs.ws.ning.NingWSPlugin + * that allows us to customise the AsyncHttpClient configuration. + */ +class ConfigurableNingWSPlugin(app: Application) extends WSPlugin { + + @volatile var loaded = false + + override lazy val enabled = true + + private val config = new DefaultWSConfigParser(app.configuration, app.classloader).parse() + + private lazy val ningAPI = new ConfigurableNingWSAPI(app, config) + + override def onStart() { + loaded = true + } + + override def onStop() { + if (loaded) { + ningAPI.resetClient() + loaded = false + } + } + + def api = ningAPI + +} + +/** + * A modified version of play.api.libs.ws.ning.NingWSAPI + * that allows us to customise the AsyncHttpClient configuration. + * + * Note: This class has to be inside the play package because + * `NingWSAPI` includes some `private[play]` members. + */ +class ConfigurableNingWSAPI(app: Application, clientConfig: WSClientConfig) extends NingWSAPI(app, clientConfig) { + + override def buildAsyncClientConfig(wsClientConfig: WSClientConfig): AsyncHttpClientConfig = { + val ahcConfigBuilder = createAndConfigureAHCConfigBuilder(app.configuration) + new NingAsyncHttpClientConfigBuilder(wsClientConfig, ahcConfigBuilder).build() + } + + private def createAndConfigureAHCConfigBuilder(config: Configuration) = { + val builder = new AsyncHttpClientConfig.Builder() + config.getInt("ws.ning.maximumConnectionLifeTime").foreach(builder.setMaxConnectionLifeTimeInMs) + config.getInt("ws.ning.idleConnectionInPoolTimeout").foreach(builder.setIdleConnectionInPoolTimeoutInMs) + config.getInt("ws.ning.webSocketIdleTimeout").foreach(builder.setWebSocketIdleTimeoutInMs) + builder + } + +} diff --git a/src/test/scala/play/plugins/PluginSpec.scala b/src/test/scala/play/plugins/PluginSpec.scala new file mode 100644 index 0000000..ac59e02 --- /dev/null +++ b/src/test/scala/play/plugins/PluginSpec.scala @@ -0,0 +1,27 @@ +package play.plugins + +import com.ning.http.client.AsyncHttpClient +import org.scalatest._ +import org.scalatestplus.play._ +import play.api.libs.ws.WS +import play.api.test.FakeApplication + +class PluginSpec extends FlatSpec with Matchers with OneAppPerSuite { + + override implicit lazy val app = new FakeApplication( + additionalPlugins = Seq("play.plugins.ConfigurableNingWSPlugin"), + additionalConfiguration = Map( + "ws.ning.maximumConnectionLifeTime" -> 100, + "ws.ning.idleConnectionInPoolTimeout" -> 200, + "ws.ning.webSocketIdleTimeout" -> 300 + ) + ) + + "App with plugin installed" should "have a properly configured AsyncHttpClient" in { + val config = WS.client.underlying[AsyncHttpClient].getConfig + config.getMaxConnectionLifeTimeInMs should be(100) + config.getIdleConnectionInPoolTimeoutInMs should be(200) + config.getWebSocketIdleTimeoutInMs should be(300) + } + +} diff --git a/version.sbt b/version.sbt new file mode 100644 index 0000000..1540682 --- /dev/null +++ b/version.sbt @@ -0,0 +1 @@ +version in ThisBuild := "0.1-SNAPSHOT"