diff --git a/.travis.yml b/.travis.yml index d208d17f35..86b65b54b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_cache: scala: - 2.11.11 - - 2.12.1 + - 2.12.4 jdk: - oraclejdk8 diff --git a/CHANGELOG.md b/CHANGELOG.md index e64929a512..c0fca0a8e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,22 @@ All notable changes to this project will be documented in this file. Note that ` ### Closed +## [finatra-17.11.0](https://github.com/twitter/finatra/tree/finatra-17.11.0) (2017-11-15) + +### Added + +### Changed + +* EmbeddedTwitterServer, EmbeddedHttpServer, and EmbeddedThriftServer flags + and args parameters changed to call-by-name. ``PHAB_ID=`D104733` + +### Fixed + +* inject-server: Ensure EmbeddedTwitterServer has started before trying to + close httpAdminClient. ``PHAB_ID=D111294`` + +### Closed + ## [finatra-17.10.0](https://github.com/twitter/finatra/tree/finatra-17.10.0) (2017-10-26) ### Added @@ -31,10 +47,14 @@ All notable changes to this project will be documented in this file. Note that ` that use the @Named binding annotation. ``PHAB_ID=D91330`` * finatra-http: Allow setting the content type of a Mustache view. - ``PHAB_ID=D91857`` + ``PHAB_ID=D91949`` ### Changed +* finatra-http: Move `FileResolver` to finatra/utils. ``PHAB_ID=D103536`` + +* finatra-utils: Move `ResponseUtils` to finatra/http. ``PHAB_ID=D103507`` + * From now on, release versions will be based on release date in the format of YY.MM.x where x is a patch number. ``PHAB_ID=D101244`` @@ -64,6 +84,13 @@ All notable changes to this project will be documented in this file. Note that ` ### Fixed +* finatra-http: Parameterized route callback inputs fail because the lookup of a + corresponding `MessageBodyManager` reader lookup does not properly handle parameterized + types such as collections. This change updates the `MessageBodyManager` `MessageBodyReader` + lookup to take into account parameterized types. This allows for a user to parse a + `Seq[T]`, or `Map[K, V]` as a route callback input type using the default Finatra + `MessageBodyReader`. ``PHAB_ID=D104277`` + * finatra-jackson: Fix issue causing `IllegalArgumentException` from Validations to be swallowed. A catch clause in the `c.t.finatra.json.internal.caseclass.jackson.FinatraCaseClassDeserializer` is too broad as it catches thrown `IllegalArgumentException`s from field validations @@ -151,7 +178,7 @@ All notable changes to this project will be documented in this file. Note that ` ### Fixed * finatra-http: Correctly return a JsonParseException when the incoming JSON is not parsable - as an expected custom case class request object. ``RB_ID=`` + as an expected custom case class request object. ``RB_ID=912529`` * finatra-http: Ensure underlying members are injected for AbstractControllers. ``RB_ID=911635`` diff --git a/benchmarks/src/test/scala/BUILD b/benchmarks/src/test/scala/BUILD index 74df80c2b3..741891f409 100644 --- a/benchmarks/src/test/scala/BUILD +++ b/benchmarks/src/test/scala/BUILD @@ -23,7 +23,7 @@ junit_tests( 'finatra/inject/inject-core/src/test/scala:test-deps', 'finatra/inject/inject-request-scope/src/main/scala', 'finatra/jackson/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-core/src/main/scala', 'util/util-slf4j-api/src/main/scala', 'util/util-stats/src/main/scala', diff --git a/build.sbt b/build.sbt index e6e69cc1da..a72cb2ff92 100644 --- a/build.sbt +++ b/build.sbt @@ -4,13 +4,13 @@ import scoverage.ScoverageKeys concurrentRestrictions in Global += Tags.limit(Tags.Test, 1) // All Twitter library releases are date versioned as YY.MM.patch -val releaseVersion = "17.10.0" +val releaseVersion = "17.11.0" lazy val buildSettings = Seq( version := releaseVersion, - scalaVersion := "2.12.1", - crossScalaVersions := Seq("2.11.11", "2.12.1"), - ivyScala := ivyScala.value.map(_.copy(overrideScalaVersion = true)), + scalaVersion := "2.12.4", + crossScalaVersions := Seq("2.11.11", "2.12.4"), + scalaModuleInfo := scalaModuleInfo.value.map(_.withOverrideScalaVersion(true)), fork in Test := true, javaOptions in Test ++= travisTestJavaOptions ) @@ -160,7 +160,7 @@ lazy val publishSettings = Seq( resourceGenerators in Compile += Def.task { val dir = (resourceManaged in Compile).value val file = dir / "com" / "twitter" / name.value / "build.properties" - val buildRev = Process("git" :: "rev-parse" :: "HEAD" :: Nil).!!.trim + val buildRev = scala.sys.process.Process("git" :: "rev-parse" :: "HEAD" :: Nil).!!.trim val buildName = new java.text.SimpleDateFormat("yyyyMMdd-HHmmss").format(new java.util.Date) val contents = s"name=${name.value}\nversion=${version.value}\nbuild_revision=$buildRev\nbuild_name=$buildName" IO.write(file, contents) @@ -530,7 +530,7 @@ lazy val utils = project previous.filter(mappingContainsAnyPath(_, utilsTestJarSources)) } ).dependsOn( - injectApp % "test->test", + injectApp % "test->test;compile->compile", injectCore % "test->test", injectServer % "test->test", injectUtils) diff --git a/doc/src/sphinx/index.rst b/doc/src/sphinx/index.rst index 770006417c..ccd7fa7ec8 100644 --- a/doc/src/sphinx/index.rst +++ b/doc/src/sphinx/index.rst @@ -126,11 +126,13 @@ To continue getting started, please see the `Finatra User's Guide `__ -- `Scaladocs `__ -- `Finagle Blog `__ -- `Presentations `__ -- `Forum `__ +.. toctree:: + + user-guide/index + Scaladocs + Finagle Blog + presentations/index + Forum Contributing ------------ diff --git a/doc/src/sphinx/presentations/index.rst b/doc/src/sphinx/presentations/index.rst index fa3eb4e655..c7a5780ad3 100644 --- a/doc/src/sphinx/presentations/index.rst +++ b/doc/src/sphinx/presentations/index.rst @@ -1,3 +1,5 @@ +.. _presentations: + Finatra Presentations ===================== diff --git a/doc/src/sphinx/user-guide/logging/logback.rst b/doc/src/sphinx/user-guide/logging/logback.rst index 613a7075f4..60627d9630 100644 --- a/doc/src/sphinx/user-guide/logging/logback.rst +++ b/doc/src/sphinx/user-guide/logging/logback.rst @@ -46,9 +46,7 @@ Examples See the `logback.xml `__ -and -`logback-test.xml `__ -configuration files in the +configuration file in the `hello-world `__ example project for example Logback configurations. diff --git a/examples/benchmark-server/src/main/scala/BUILD b/examples/benchmark-server/src/main/scala/BUILD index b7dc10ec1e..fc83bc9ef5 100644 --- a/examples/benchmark-server/src/main/scala/BUILD +++ b/examples/benchmark-server/src/main/scala/BUILD @@ -13,7 +13,7 @@ scala_library( 'finatra/inject/inject-core/src/main/scala', 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/hello-world/src/main/scala/BUILD b/examples/hello-world/src/main/scala/BUILD index 128f11a660..4c21dcf104 100644 --- a/examples/hello-world/src/main/scala/BUILD +++ b/examples/hello-world/src/main/scala/BUILD @@ -9,7 +9,7 @@ scala_library( 'finatra/inject/inject-core/src/main/scala', 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala:scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/java-http-server/src/main/java/BUILD b/examples/java-http-server/src/main/java/BUILD index d774aed9e8..e3efd5ce3b 100644 --- a/examples/java-http-server/src/main/java/BUILD +++ b/examples/java-http-server/src/main/java/BUILD @@ -13,7 +13,7 @@ java_library( 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', 'finatra/utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala', diff --git a/examples/java-http-server/src/test/java/BUILD b/examples/java-http-server/src/test/java/BUILD index 8d77f16948..6b3d5caaba 100644 --- a/examples/java-http-server/src/test/java/BUILD +++ b/examples/java-http-server/src/test/java/BUILD @@ -17,7 +17,7 @@ junit_tests( 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-server/src/test/scala:test-deps', 'finatra/inject/inject-slf4j/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-logging/src/main/scala', diff --git a/examples/java-server/src/main/java/BUILD b/examples/java-server/src/main/java/BUILD index dd4f99d4ee..72e6f0dd13 100644 --- a/examples/java-server/src/main/java/BUILD +++ b/examples/java-server/src/main/java/BUILD @@ -14,7 +14,7 @@ java_library( 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala', diff --git a/examples/java-server/src/test/java/BUILD b/examples/java-server/src/test/java/BUILD index 3849f4230c..b5ba3689dc 100644 --- a/examples/java-server/src/test/java/BUILD +++ b/examples/java-server/src/test/java/BUILD @@ -12,7 +12,7 @@ junit_tests( 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-server/src/test/scala:test-deps', 'finatra/inject/inject-slf4j/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-logging/src/main/scala', diff --git a/examples/java-thrift-server/thrift-example-server/src/main/java/BUILD b/examples/java-thrift-server/thrift-example-server/src/main/java/BUILD index 01bf9971fa..6c1529d5aa 100644 --- a/examples/java-thrift-server/thrift-example-server/src/main/java/BUILD +++ b/examples/java-thrift-server/thrift-example-server/src/main/java/BUILD @@ -1,6 +1,5 @@ java_library( dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject:guice', '3rdparty/jvm/javax/inject:javax.inject', '3rdparty/jvm/org/apache/thrift:libthrift-0.5.0', @@ -16,7 +15,7 @@ java_library( 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', 'finatra/thrift/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala', diff --git a/examples/java-thrift-server/thrift-example-server/src/test/java/BUILD b/examples/java-thrift-server/thrift-example-server/src/test/java/BUILD index c58ff72583..ecefea479b 100644 --- a/examples/java-thrift-server/thrift-example-server/src/test/java/BUILD +++ b/examples/java-thrift-server/thrift-example-server/src/test/java/BUILD @@ -17,7 +17,7 @@ junit_tests( 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/thrift/src/main/scala', 'finatra/thrift/src/test/scala:test-deps', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-logging/src/main/scala', diff --git a/examples/streaming-example/src/main/scala/BUILD b/examples/streaming-example/src/main/scala/BUILD index c55b8d7f84..088aa6ac39 100644 --- a/examples/streaming-example/src/main/scala/BUILD +++ b/examples/streaming-example/src/main/scala/BUILD @@ -8,7 +8,7 @@ scala_library( 'finatra/inject/inject-core/src/main/scala', 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala:scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/thrift-server/thrift-example-server/src/main/scala/BUILD b/examples/thrift-server/thrift-example-server/src/main/scala/BUILD index 77331da4ec..55ee2432ba 100644 --- a/examples/thrift-server/thrift-example-server/src/main/scala/BUILD +++ b/examples/thrift-server/thrift-example-server/src/main/scala/BUILD @@ -18,7 +18,7 @@ scala_library( 'finatra/thrift/src/main/scala', 'finatra/thrift/src/main/thrift:thrift-scala', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/twitter-clone/src/main/scala/BUILD b/examples/twitter-clone/src/main/scala/BUILD index 03160ee047..b7200359b4 100644 --- a/examples/twitter-clone/src/main/scala/BUILD +++ b/examples/twitter-clone/src/main/scala/BUILD @@ -22,7 +22,7 @@ scala_library( 'finatra/inject/inject-utils/src/main/scala', 'finatra/jackson/src/main/scala', 'finatra/utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/twitter-clone/src/main/scala/finatra/quickstart/modules/FirebaseHttpClientModule.scala b/examples/twitter-clone/src/main/scala/finatra/quickstart/modules/FirebaseHttpClientModule.scala index e3abc1c675..6aecab56bc 100644 --- a/examples/twitter-clone/src/main/scala/finatra/quickstart/modules/FirebaseHttpClientModule.scala +++ b/examples/twitter-clone/src/main/scala/finatra/quickstart/modules/FirebaseHttpClientModule.scala @@ -1,7 +1,7 @@ package finatra.quickstart.modules import com.twitter.finatra.httpclient.modules.HttpClientModule -import com.twitter.finatra.utils.ResponseUtils._ +import com.twitter.finatra.http.response.ResponseUtils._ import com.twitter.inject.conversions.time._ import com.twitter.inject.utils.RetryPolicyUtils._ diff --git a/examples/web-dashboard/src/main/scala/BUILD b/examples/web-dashboard/src/main/scala/BUILD index f839613669..0e5a727976 100644 --- a/examples/web-dashboard/src/main/scala/BUILD +++ b/examples/web-dashboard/src/main/scala/BUILD @@ -19,7 +19,7 @@ scala_library( 'finatra/inject/inject-slf4j/src/main/scala:scala', 'finatra/inject/inject-thrift-client/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/examples/web-dashboard/src/main/scala/com/twitter/web/dashboard/controllers/DashboardController.scala b/examples/web-dashboard/src/main/scala/com/twitter/web/dashboard/controllers/DashboardController.scala index f356803862..b47168e71d 100644 --- a/examples/web-dashboard/src/main/scala/com/twitter/web/dashboard/controllers/DashboardController.scala +++ b/examples/web-dashboard/src/main/scala/com/twitter/web/dashboard/controllers/DashboardController.scala @@ -836,7 +836,7 @@ class DashboardController extends Controller { /** * An example of how to serve files or an index. If the path param of "*" matches the name/path - * of a file that can be resolved by the [[com.twitter.finatra.http.routing.FileResolver]] + * of a file that can be resolved by the [[com.twitter.finatra.utils.FileResolver]] * then the file will be returned. Otherwise the file at 'indexPath' (in this case 'index.html') * will be returned. This is useful for building "single-page" web applications. * diff --git a/http/src/main/scala/BUILD b/http/src/main/scala/BUILD index 93ff59f5de..51c631cd5d 100644 --- a/http/src/main/scala/BUILD +++ b/http/src/main/scala/BUILD @@ -43,7 +43,7 @@ scala_library( 'finatra/jackson/src/main/scala', 'finatra/utils/src/main/java', 'finatra/utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-collection/src/main/scala', 'util/util-core/src/main/scala', diff --git a/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/CallbackConverter.scala b/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/CallbackConverter.scala index 1709a5d90d..4ed784f17e 100644 --- a/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/CallbackConverter.scala +++ b/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/CallbackConverter.scala @@ -6,10 +6,10 @@ import com.twitter.finatra.http.response.{ResponseBuilder, StreamingResponse} import com.twitter.finatra.json.FinatraObjectMapper import com.twitter.finatra.json.internal.streaming.JsonStreamParser import com.twitter.io.Buf -import com.twitter.util.{FuturePool, Promise, Future} +import com.twitter.util.{Future, FuturePool, Promise} import javax.inject.Inject -import scala.concurrent.{Future => ScalaFuture, ExecutionContext => ScalaExecutionContext} -import scala.util.{Success, Failure} +import scala.concurrent.{ExecutionContext => ScalaExecutionContext, Future => ScalaFuture} +import scala.util.{Failure, Success} private[http] class CallbackConverter @Inject()( messageBodyManager: MessageBodyManager, @@ -20,8 +20,6 @@ private[http] class CallbackConverter @Inject()( /* Public */ - // Note we use Manifest here as we support Scala 2.10 and reflection is not thread-safe in 2.10 (precluding the use - // of typeTag and/or classTag). See: http://docs.scala-lang.org/overviews/reflection/thread-safety.html def convertToFutureResponse[RequestType: Manifest, ResponseType: Manifest]( callback: RequestType => ResponseType ): Request => Future[Response] = { diff --git a/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/MessageBodyManager.scala b/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/MessageBodyManager.scala index d7a9e4f4ad..36becc4440 100644 --- a/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/MessageBodyManager.scala +++ b/http/src/main/scala/com/twitter/finatra/http/internal/marshalling/MessageBodyManager.scala @@ -1,7 +1,9 @@ package com.twitter.finatra.http.internal.marshalling +import com.google.inject.internal.MoreTypes.ParameterizedTypeImpl import com.twitter.finagle.http.Request import com.twitter.finatra.http.marshalling._ +import com.twitter.finatra.response.Mustache import com.twitter.inject.Injector import com.twitter.inject.TypeUtils.singleTypeParam import com.twitter.inject.conversions.map._ @@ -11,7 +13,6 @@ import java.util.concurrent.ConcurrentHashMap import javax.inject.{Inject, Singleton} import net.codingwell.scalaguice._ import scala.collection.mutable -import scala.reflect.ScalaSignature @Singleton class MessageBodyManager @Inject()( @@ -22,6 +23,8 @@ class MessageBodyManager @Inject()( private val classTypeToReader = mutable.Map[Type, MessageBodyReader[Any]]() private val classTypeToWriter = mutable.Map[Type, MessageBodyWriter[Any]]() + + private val writerAnnotations: Seq[Class[_ <: Annotation]] = Seq(classOf[Mustache]) private val annotationTypeToWriter = mutable.Map[Type, MessageBodyWriter[Any]]() private val readerCache = @@ -54,8 +57,7 @@ class MessageBodyManager @Inject()( annotationTypeToWriter(annot) = messageBodyWriter.asInstanceOf[MessageBodyWriter[Any]] } - def addByComponentType[M <: MessageBodyComponent: Manifest, T <: MessageBodyWriter[_]: Manifest]() - : Unit = { + def addByComponentType[M <: MessageBodyComponent: Manifest, T <: MessageBodyWriter[_]: Manifest](): Unit = { val messageBodyWriter = injector.instance[T] val componentType = manifest[M].runtimeClass.asInstanceOf[Class[M]] writerCache.putIfAbsent(componentType, messageBodyWriter.asInstanceOf[MessageBodyWriter[Any]]) @@ -71,7 +73,7 @@ class MessageBodyManager @Inject()( val requestManifest = manifest[T] readerCache.atomicGetOrElseUpdate(requestManifest, { val objType = typeLiteral(requestManifest).getType - classTypeToReader.get(objType) orElse findReaderBySuperType(objType) + classTypeToReader.get(objType).orElse(findReaderBySuperType(objType)) }) match { case Some(reader) => reader.parse(request).asInstanceOf[T] @@ -80,28 +82,41 @@ class MessageBodyManager @Inject()( } } - private def findReaderBySuperType(t: Type): Option[MessageBodyReader[Any]] = { - classTypeToReader - .find { - case (tpe, _) => tpe.asInstanceOf[Class[_]].isAssignableFrom(t.asInstanceOf[Class[_]]) - } - .map { case (_, messageBodyReader) => messageBodyReader } - } - - // Note: writerCache is bounded on the number of unique classes returned from controller routes */ + /* Note: writerCache is bounded on the number of unique classes returned from controller routes */ def writer(obj: Any): MessageBodyWriter[Any] = { val objClass = obj.getClass writerCache.atomicGetOrElseUpdate(objClass, { - (classTypeToWriter - .get(objClass) orElse classAnnotationToWriter(objClass)) getOrElse defaultMessageBodyWriter + classTypeToWriter + .get(objClass) + .orElse(classAnnotationToWriter(objClass)) + .getOrElse(defaultMessageBodyWriter) }) } /* Private */ + private def findReaderBySuperType(t: Type): Option[MessageBodyReader[Any]] = { + val classTypeToReaderOption: Option[(Type, MessageBodyReader[Any])] = t match { + case _ : ParameterizedTypeImpl => + None // User registered MessageBodyComponents with parameterized types are not supported, so do not attempt to look up a reader + case _ => + classTypeToReader + .find { case (tpe, _) => + tpe.asInstanceOf[Class[_]] + .isAssignableFrom(t.asInstanceOf[Class[_]]) + } + } + classTypeToReaderOption.map { case (_, messageBodyReader) => messageBodyReader } + } + private def add[MessageBodyComp: Manifest](typeToReadOrWrite: Type): Unit = { - val messageBodyComponent = injector.instance[MessageBodyComp] - addComponent(messageBodyComponent, typeToReadOrWrite) + typeToReadOrWrite match { + case p: ParameterizedTypeImpl => + throw new IllegalArgumentException("Adding a message body component with parameterized types, e.g. MessageBodyReader[Map[String, String]] is not supported.") + case _ => + val messageBodyComponent = injector.instance[MessageBodyComp] + addComponent(messageBodyComponent, typeToReadOrWrite) + } } private def addComponent(messageBodyComponent: Any, typeToReadOrWrite: Type): Unit = { @@ -113,12 +128,12 @@ class MessageBodyManager @Inject()( } } - //TODO: Support more than the first annotation (e.g. @Mustache could be combined w/ other annotations) private def classAnnotationToWriter(clazz: Class[_]): Option[MessageBodyWriter[Any]] = { - val annotations = clazz.getAnnotations filterNot { _.annotationType == classOf[ScalaSignature] } - if (annotations.length >= 1) - annotationTypeToWriter.get(annotations.head.annotationType) - else - None + // we stop at the first supported annotation for looking up a writer + clazz.getAnnotations.collectFirst { + case annotation if writerAnnotations.contains(annotation.annotationType()) => annotation + }.flatMap { annotation => + annotationTypeToWriter.get(annotation.annotationType) + } } } diff --git a/http/src/main/scala/com/twitter/finatra/http/modules/MustacheModule.scala b/http/src/main/scala/com/twitter/finatra/http/modules/MustacheModule.scala index 22bb4f0a5c..d5f13f387b 100644 --- a/http/src/main/scala/com/twitter/finatra/http/modules/MustacheModule.scala +++ b/http/src/main/scala/com/twitter/finatra/http/modules/MustacheModule.scala @@ -3,7 +3,7 @@ package com.twitter.finatra.http.modules import com.github.mustachejava.{DefaultMustacheFactory, Mustache, MustacheFactory} import com.google.inject.Provides import com.twitter.finatra.http.internal.marshalling.mustache.ScalaObjectHandler -import com.twitter.finatra.http.routing.FileResolver +import com.twitter.finatra.utils.FileResolver import com.twitter.inject.TwitterModule import com.twitter.inject.annotations.Flag import java.io._ diff --git a/http/src/main/scala/com/twitter/finatra/http/response/ResponseBuilder.scala b/http/src/main/scala/com/twitter/finatra/http/response/ResponseBuilder.scala index d3df6351dc..5653396a3f 100644 --- a/http/src/main/scala/com/twitter/finatra/http/response/ResponseBuilder.scala +++ b/http/src/main/scala/com/twitter/finatra/http/response/ResponseBuilder.scala @@ -8,7 +8,7 @@ import com.twitter.finatra.http.contexts.RouteInfo import com.twitter.finatra.http.exceptions.HttpResponseException import com.twitter.finatra.http.internal.marshalling.MessageBodyManager import com.twitter.finatra.http.marshalling.mustache.MustacheBodyComponent -import com.twitter.finatra.http.routing.FileResolver +import com.twitter.finatra.utils.FileResolver import com.twitter.finatra.json.FinatraObjectMapper import com.twitter.inject.Logging import com.twitter.inject.annotations.Flag diff --git a/utils/src/main/scala/com/twitter/finatra/utils/ResponseUtils.scala b/http/src/main/scala/com/twitter/finatra/http/response/ResponseUtils.scala similarity index 97% rename from utils/src/main/scala/com/twitter/finatra/utils/ResponseUtils.scala rename to http/src/main/scala/com/twitter/finatra/http/response/ResponseUtils.scala index c7cbb7d068..a22d7d934d 100644 --- a/utils/src/main/scala/com/twitter/finatra/utils/ResponseUtils.scala +++ b/http/src/main/scala/com/twitter/finatra/http/response/ResponseUtils.scala @@ -1,4 +1,4 @@ -package com.twitter.finatra.utils +package com.twitter.finatra.http.response import com.twitter.finagle.http.{Response, Status} import com.twitter.finagle.http.Status._ diff --git a/http/src/test/java/BUILD b/http/src/test/java/BUILD index 36d3070ef1..cfe870041a 100644 --- a/http/src/test/java/BUILD +++ b/http/src/test/java/BUILD @@ -20,7 +20,7 @@ junit_tests( 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', 'finatra/utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala', diff --git a/http/src/test/scala/BUILD b/http/src/test/scala/BUILD index ceee76f04b..9ad74544e5 100644 --- a/http/src/test/scala/BUILD +++ b/http/src/test/scala/BUILD @@ -49,7 +49,7 @@ junit_tests( 'finatra/jackson/src/test/scala:test-deps', 'finatra/utils/src/main/scala', 'finatra/utils/src/test/scala:test-deps', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', @@ -90,7 +90,7 @@ scala_library(name="test-deps", 'finatra/inject/inject-server/src/test/scala:test-deps', 'finatra/jackson/src/main/scala', 'finatra/jackson/src/test/scala:test-deps', - 'twitter-server/src/main/scala:scala', + 'twitter-server/server/src/main/scala:scala', 'util/util-core/src/main/scala', 'util/util-slf4j-api/src/main/scala', ], diff --git a/http/src/test/scala/com/twitter/finatra/http/EmbeddedHttpServer.scala b/http/src/test/scala/com/twitter/finatra/http/EmbeddedHttpServer.scala index 225d2cb9ce..513c2ac0ec 100644 --- a/http/src/test/scala/com/twitter/finatra/http/EmbeddedHttpServer.scala +++ b/http/src/test/scala/com/twitter/finatra/http/EmbeddedHttpServer.scala @@ -43,8 +43,8 @@ import scala.util.control.NonFatal */ class EmbeddedHttpServer( val twitterServer: Ports, - flags: Map[String, String] = Map(), - args: Seq[String] = Seq(), + flags: => Map[String, String] = Map(), + args: => Seq[String] = Seq(), waitForWarmup: Boolean = true, stage: Stage = Stage.DEVELOPMENT, useSocksProxy: Boolean = false, diff --git a/utils/src/test/scala/com/twitter/finatra/tests/utils/HttpRetryUtilsTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/HttpRetryUtilsTest.scala similarity index 85% rename from utils/src/test/scala/com/twitter/finatra/tests/utils/HttpRetryUtilsTest.scala rename to http/src/test/scala/com/twitter/finatra/http/tests/HttpRetryUtilsTest.scala index 9e61856096..cce6bfbc98 100644 --- a/utils/src/test/scala/com/twitter/finatra/tests/utils/HttpRetryUtilsTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/HttpRetryUtilsTest.scala @@ -1,11 +1,11 @@ -package com.twitter.finatra.tests.utils +package com.twitter.finatra.http.tests -import com.twitter.finagle.http.{Status, Response} -import com.twitter.finatra.utils.ResponseUtils +import com.twitter.finagle.http.{Response, Status} +import com.twitter.finatra.http.response.ResponseUtils import com.twitter.inject.Test import com.twitter.inject.conversions.time._ import com.twitter.inject.utils.{RetryPolicyUtils, RetryUtils} -import com.twitter.util.{Future, Await} +import com.twitter.util.{Await, Future} class HttpRetryUtilsTest extends Test { diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/main/controllers/DoEverythingController.scala b/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/main/controllers/DoEverythingController.scala index 3b51b128e5..5d3b094a94 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/main/controllers/DoEverythingController.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/main/controllers/DoEverythingController.scala @@ -855,6 +855,22 @@ class DoEverythingController @Inject()( response.internalServerError(e.getMessage) } } + + post("/seq") { r: Seq[String] => + r + } + + post("/map") { r: Map[String, String] => + r + } + + post("/seq2") { r: Request => + objectMapper.parse[Seq[String]](r.contentString) + } + + post("/seqCaseClass") { r: Seq[TestUser] => + r + } } case class MultipleInjectableValueParams(@RouteParam @QueryParam id: String) diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/test/DoEverythingServerFeatureTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/test/DoEverythingServerFeatureTest.scala index b382d0f3c4..f378b57352 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/test/DoEverythingServerFeatureTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/integration/doeverything/test/DoEverythingServerFeatureTest.scala @@ -2271,4 +2271,41 @@ class DoEverythingServerFeatureTest extends FeatureTest { withBody = "Class [class java.lang.String] is not supported by class com.twitter.finatra.json.internal.caseclass.validation.validators.MaxValidator" ) } + + test("POST /seq") { + server.httpPost( + "/seq", + """ + ["foo", "bar", "baz"] + """, + andExpect = Ok) + } + + test("POST /map") { + server.httpPost( + "/map", + """ + {"foo": "bar", "baz": "bubble"} + """, + andExpect = Ok) + } + + test("POST /seq2") { + server.httpPost( + "/seq2", + """ + ["foo", "bar", "baz"] + """, + andExpect = Ok) + } + + test("POST /seqCaseClass") { + server.httpPost( + "/seqCaseClass", + """ + [{"name": "a"}, {"name": "b"}, {"name": "c"}] + """, + andExpect = BadRequest, + withJsonBody = """{"errors":["name: size [1] is not between 2 and 20"]}""") + } } diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/integration/multiserver/test/MultiServerFeatureTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/integration/multiserver/test/MultiServerFeatureTest.scala index ff03984092..83e6f94239 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/integration/multiserver/test/MultiServerFeatureTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/integration/multiserver/test/MultiServerFeatureTest.scala @@ -13,6 +13,14 @@ class MultiServerFeatureTest extends Test with HttpTest { val add2Server = new EmbeddedHttpServer(new Add2Server, flags = Map(resolverMap("add1-server", add1Server))) + override def beforeAll() = { + assert(!add1Server.isStarted) + assert(!add2Server.isStarted) + + add1Server.assertHealthy() + add2Server.assertHealthy() + } + override def afterAll() = { add1Server.close() add2Server.close() diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/marshalling/MessageBodyManagerTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/marshalling/MessageBodyManagerTest.scala index b75d92b3f8..4341377d71 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/marshalling/MessageBodyManagerTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/marshalling/MessageBodyManagerTest.scala @@ -34,6 +34,12 @@ class MessageBodyManagerTest extends Test with Mockito { test("parse father impl with father MBR") { messageBodyManager.read[Son](request) should equal(Son("Son")) } + + test("parse map with MBR not supported") { + intercept[IllegalArgumentException] { + messageBodyManager.add[MapIntDoubleMessageBodyReader]() + } + } } case class Car2(name: String) @@ -65,3 +71,7 @@ class FatherMessageBodyReader extends MessageBodyReader[Father] { } } } + +class MapIntDoubleMessageBodyReader extends MessageBodyReader[Map[Int, Double]] { + def parse[M: Manifest](request: Request): Map[Int, Double] = Map(1 -> 0.0, 2 -> 3.14, 3 -> 0.577) +} diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseBuilderTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseBuilderTest.scala index 993ca0290c..70c983de6a 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseBuilderTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseBuilderTest.scala @@ -5,8 +5,8 @@ import com.twitter.finagle.http.{Cookie => FinagleCookie, Request, Response, Sta import com.twitter.finagle.stats.StatsReceiver import com.twitter.finatra.http.internal.marshalling.MessageBodyManager import com.twitter.finatra.http.response.ResponseBuilder -import com.twitter.finatra.http.routing.FileResolver import com.twitter.finatra.json.FinatraObjectMapper +import com.twitter.finatra.utils.FileResolver import com.twitter.inject.{Test, Mockito} import com.twitter.util.Await import java.io.{File, FileWriter} diff --git a/utils/src/test/scala/com/twitter/finatra/tests/utils/ResponseUtilsTest.scala b/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseUtilsTest.scala similarity index 97% rename from utils/src/test/scala/com/twitter/finatra/tests/utils/ResponseUtilsTest.scala rename to http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseUtilsTest.scala index 1f7b51a5f6..80183b01bd 100644 --- a/utils/src/test/scala/com/twitter/finatra/tests/utils/ResponseUtilsTest.scala +++ b/http/src/test/scala/com/twitter/finatra/http/tests/response/ResponseUtilsTest.scala @@ -1,7 +1,7 @@ package com.twitter.finatra.tests.utils import com.twitter.finagle.http.{Response, Status, Version} -import com.twitter.finatra.utils.ResponseUtils +import com.twitter.finatra.http.response.ResponseUtils import com.twitter.inject.Test class ResponseUtilsTest extends Test { diff --git a/httpclient/src/main/scala/BUILD b/httpclient/src/main/scala/BUILD index aeb7d2524e..db1fb4275b 100644 --- a/httpclient/src/main/scala/BUILD +++ b/httpclient/src/main/scala/BUILD @@ -5,7 +5,6 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/guava:guava', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', diff --git a/httpclient/src/test/scala/BUILD b/httpclient/src/test/scala/BUILD index 656b771a1d..7e78a61346 100644 --- a/httpclient/src/test/scala/BUILD +++ b/httpclient/src/test/scala/BUILD @@ -22,7 +22,7 @@ junit_tests( 'finatra/inject/inject-core/src/main/scala', 'finatra/inject/inject-core/src/test/scala:test-deps', 'finatra/jackson/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-core/src/main/scala', 'util/util-slf4j-api/src/main/scala', ], diff --git a/inject-thrift-client-http-mapper/src/test/scala/BUILD b/inject-thrift-client-http-mapper/src/test/scala/BUILD index b23ccc920a..64bd3ac107 100644 --- a/inject-thrift-client-http-mapper/src/test/scala/BUILD +++ b/inject-thrift-client-http-mapper/src/test/scala/BUILD @@ -33,7 +33,7 @@ junit_tests( 'finatra/thrift/src/main/thrift:thrift-scala', 'finatra/thrift/src/test/scala:test-deps', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/inject/inject-app/src/test/scala/BUILD b/inject/inject-app/src/test/scala/BUILD index 81b9162089..d7fb272579 100644 --- a/inject/inject-app/src/test/scala/BUILD +++ b/inject/inject-app/src/test/scala/BUILD @@ -34,7 +34,6 @@ scala_library(name="test-deps", ), dependencies=[ '//:scala-reflect', - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject/extensions:guice-testlib', diff --git a/inject/inject-core/src/main/scala/BUILD b/inject/inject-core/src/main/scala/BUILD index 64134b04a5..b35bac71bd 100644 --- a/inject/inject-core/src/main/scala/BUILD +++ b/inject/inject-core/src/main/scala/BUILD @@ -6,7 +6,6 @@ scala_library( ), dependencies=[ '//:scala-reflect', - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject:guice', diff --git a/inject/inject-core/src/test/scala/com/twitter/inject/TestMixin.scala b/inject/inject-core/src/test/scala/com/twitter/inject/TestMixin.scala index 89328b1fba..1c829d582c 100644 --- a/inject/inject-core/src/test/scala/com/twitter/inject/TestMixin.scala +++ b/inject/inject-core/src/test/scala/com/twitter/inject/TestMixin.scala @@ -1,5 +1,6 @@ package com.twitter.inject +import com.twitter.conversions.time._ import com.twitter.util.{Await, Future} import java.util.TimeZone import org.apache.commons.io.IOUtils @@ -32,7 +33,7 @@ trait TestMixin /* Overrides */ - override protected def afterAll() = { + override protected def afterAll(): Unit = { super.afterAll() pool.executor.shutdown() } @@ -41,16 +42,16 @@ trait TestMixin protected lazy val pool = PoolUtils.newUnboundedPool("Test " + getClass.getSimpleName) - protected def setUtcTimeZone() = { + protected def setUtcTimeZone(): Unit = { DateTimeZone.setDefault(DateTimeZone.UTC) TimeZone.setDefault(TimeZone.getTimeZone("UTC")) } - protected def resourceAsString(resource: String) = { + protected def resourceAsString(resource: String): String = { IOUtils.toString(getClass.getResourceAsStream(resource)) } - protected def sleep(duration: Duration, verbose: Boolean = false) { + protected def sleep(duration: Duration, verbose: Boolean = false): Unit = { if (verbose) { println("Starting sleep for " + duration) } @@ -62,21 +63,21 @@ trait TestMixin } } - protected def assertFuture[A](result: Future[A], expected: Future[A]) { - val resultVal = Await.result(result) - val expectedVal = Await.result(expected) + protected def assertFuture[A](result: Future[A], expected: Future[A]): Unit = { + val resultVal = Await.result(result, 5.seconds) + val expectedVal = Await.result(expected, 5.seconds) resultVal should equal(expectedVal) } - protected def assertFutureValue[A](result: Future[A], expected: A) { - val resultVal = Await.result(result) - val expectedVal = Await.result(Future.value(expected)) + protected def assertFutureValue[A](result: Future[A], expected: A): Unit = { + val resultVal = Await.result(result, 5.seconds) + val expectedVal = Await.result(Future.value(expected), 5.seconds) resultVal should equal(expectedVal) } protected def assertFailedFuture[T <: Throwable: Manifest](result: Future[_]): T = { try { - Await.result(result) + Await.result(result, 5.seconds) fail("Expected exception " + manifest[T].runtimeClass + " never thrown") } catch { case e: Throwable => @@ -87,7 +88,7 @@ trait TestMixin } } - protected def bytes(str: String) = { + protected def bytes(str: String): Array[Byte] = { str.getBytes("UTF-8") } } diff --git a/inject/inject-modules/src/main/scala/BUILD b/inject/inject-modules/src/main/scala/BUILD index 5343183393..24fae50bb7 100644 --- a/inject/inject-modules/src/main/scala/BUILD +++ b/inject/inject-modules/src/main/scala/BUILD @@ -5,7 +5,6 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject:guice', diff --git a/inject/inject-request-scope/src/main/scala/BUILD b/inject/inject-request-scope/src/main/scala/BUILD index b9cdf472e6..10e1c2f5da 100644 --- a/inject/inject-request-scope/src/main/scala/BUILD +++ b/inject/inject-request-scope/src/main/scala/BUILD @@ -5,7 +5,6 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject:guice', diff --git a/inject/inject-server/src/main/scala/BUILD b/inject/inject-server/src/main/scala/BUILD index 5a80a5ef2c..2edebc209b 100644 --- a/inject/inject-server/src/main/scala/BUILD +++ b/inject/inject-server/src/main/scala/BUILD @@ -5,7 +5,6 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject:guice', diff --git a/inject/inject-server/src/main/scala/com/twitter/inject/server/TwitterServer.scala b/inject/inject-server/src/main/scala/com/twitter/inject/server/TwitterServer.scala index 912c7d4b6c..8a40f48896 100644 --- a/inject/inject-server/src/main/scala/com/twitter/inject/server/TwitterServer.scala +++ b/inject/inject-server/src/main/scala/com/twitter/inject/server/TwitterServer.scala @@ -218,8 +218,8 @@ trait TwitterServer @deprecated("For backwards compatibility of defined flags", "2017-10-06") private[server] trait DeprecatedLogging extends com.twitter.logging.Logging { self: App => - @deprecated("For backwards compatibility only. Do not attempt to use this logger.", "2017-10-06") - override lazy val log: com.twitter.logging.Logger = com.twitter.logging.NullLogger + @deprecated("For backwards compatibility only.", "2017-10-06") + override lazy val log: com.twitter.logging.Logger = com.twitter.logging.Logger(name) override def configureLoggerFactories(): Unit = {} } diff --git a/inject/inject-server/src/test/scala/BUILD b/inject/inject-server/src/test/scala/BUILD index 351f2cbfa5..e98c7ee4d5 100644 --- a/inject/inject-server/src/test/scala/BUILD +++ b/inject/inject-server/src/test/scala/BUILD @@ -20,7 +20,7 @@ junit_tests( 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-server/src/test/scala:test-deps', 'finatra/inject/inject-slf4j/src/main/scala:scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', @@ -63,7 +63,7 @@ scala_library(name="test-deps", 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala', 'finatra/inject/inject-utils/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-logging/src/main/scala', diff --git a/inject/inject-server/src/test/scala/com/twitter/inject/server/EmbeddedTwitterServer.scala b/inject/inject-server/src/test/scala/com/twitter/inject/server/EmbeddedTwitterServer.scala index 5b88b6b635..ef712d4d43 100644 --- a/inject/inject-server/src/test/scala/com/twitter/inject/server/EmbeddedTwitterServer.scala +++ b/inject/inject-server/src/test/scala/com/twitter/inject/server/EmbeddedTwitterServer.scala @@ -12,13 +12,13 @@ import com.twitter.finagle.service.RetryPolicy._ import com.twitter.finagle.stats.{InMemoryStatsReceiver, StatsReceiver} import com.twitter.finagle.{ChannelClosedException, Http, Service} import com.twitter.inject.PoolUtils -import com.twitter.inject.app.{InjectionServiceWithNamedAnnotationModule, InjectionServiceWithAnnotationModule, InjectionServiceModule, StartupTimeoutException} +import com.twitter.inject.app.{InjectionServiceModule, InjectionServiceWithAnnotationModule, InjectionServiceWithNamedAnnotationModule, StartupTimeoutException} import com.twitter.inject.conversions.map._ import com.twitter.inject.modules.InMemoryStatsReceiverModule import com.twitter.inject.server.EmbeddedTwitterServer._ import com.twitter.inject.server.PortUtils._ import com.twitter.server.AdminHttpServer -import com.twitter.util.lint.{Rule, GlobalRules} +import com.twitter.util.lint.{GlobalRules, Rule} import com.twitter.util.{Await, Duration, Future, Stopwatch, Try} import java.lang.annotation.Annotation import java.net.{InetSocketAddress, URI} @@ -70,8 +70,8 @@ object EmbeddedTwitterServer { */ class EmbeddedTwitterServer( twitterServer: com.twitter.server.TwitterServer, - flags: Map[String, String] = Map(), - args: Seq[String] = Seq(), + flags: => Map[String, String] = Map(), + args: => Seq[String] = Seq(), waitForWarmup: Boolean = true, stage: Stage = Stage.DEVELOPMENT, useSocksProxy: Boolean = false, @@ -223,7 +223,8 @@ class EmbeddedTwitterServer( if (!closed) { infoBanner(s"Closing ${this.getClass.getSimpleName}: " + name) try { - Await.all(httpAdminClient.close(), twitterServer.close()) + val adminClientCloseFuture = if (started) httpAdminClient.close() else Future.Done + Await.all(adminClientCloseFuture, twitterServer.close()) mainRunnerFuturePool.executor.shutdown() } catch { case NonFatal(e) => diff --git a/inject/inject-server/src/test/scala/com/twitter/inject/server/tests/EmbeddedTwitterServerIntegrationTest.scala b/inject/inject-server/src/test/scala/com/twitter/inject/server/tests/EmbeddedTwitterServerIntegrationTest.scala index 5e502a363a..4c65a8f6ca 100644 --- a/inject/inject-server/src/test/scala/com/twitter/inject/server/tests/EmbeddedTwitterServerIntegrationTest.scala +++ b/inject/inject-server/src/test/scala/com/twitter/inject/server/tests/EmbeddedTwitterServerIntegrationTest.scala @@ -1,13 +1,15 @@ package com.twitter.inject.server.tests +import com.google.inject.{Provides, Stage} import com.google.inject.name.Names import com.twitter.finagle.{Http, Service} import com.twitter.finagle.http.{Request, Response, Status} import com.twitter.inject.server.{EmbeddedTwitterServer, TwitterServer} import com.twitter.inject.{Logging, Test, TwitterModule} -import com.twitter.util.{Future, Await} -import com.twitter.util.lint.{Rules, RulesImpl, GlobalRules, Rule, Issue, Category} +import com.twitter.util.{Await, Future} +import com.twitter.util.lint.{Category, GlobalRules, Issue, Rule, Rules, RulesImpl} import com.twitter.util.registry.{GlobalRegistry, SimpleRegistry} +import javax.inject.Singleton import org.apache.commons.lang.RandomStringUtils class EmbeddedTwitterServerIntegrationTest extends Test { @@ -120,6 +122,28 @@ class EmbeddedTwitterServerIntegrationTest extends Test { } } + test("server#injector error") { + val server = new EmbeddedTwitterServer( + stage = Stage.PRODUCTION, + twitterServer = new TwitterServer { + override val modules = Seq(new TwitterModule() { + @Provides + @Singleton + def providesFoo: Integer = { + throw new Exception("Yikes") + } + }) + }).bind[String]("helloworld") + try { + val e = intercept[Exception] { + server.injector.instance[String] should be("helloworld") + } + e.getCause.getMessage should be("Yikes") + } finally{ + server.close() + } + } + // Currently fails in sbt ignore("server#fail startup because of linting violations") { val rules = mkRules(alwaysRule1, alwaysRule2, neverRule) diff --git a/inject/inject-thrift-client/src/test/scala/BUILD b/inject/inject-thrift-client/src/test/scala/BUILD index 5d6765377e..7901075c8c 100644 --- a/inject/inject-thrift-client/src/test/scala/BUILD +++ b/inject/inject-thrift-client/src/test/scala/BUILD @@ -30,7 +30,7 @@ junit_tests( 'finatra/inject/inject-thrift/src/main/scala:scala', 'finatra/thrift/src/test/scala:test-deps', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/inject/inject-utils/src/main/scala/BUILD b/inject/inject-utils/src/main/scala/BUILD index 8ad0b32a2b..b89d9c04d9 100644 --- a/inject/inject-utils/src/main/scala/BUILD +++ b/inject/inject-utils/src/main/scala/BUILD @@ -5,7 +5,6 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/github/nscala_time:nscala_time', '3rdparty/jvm/commons-lang', '3rdparty/jvm/joda-time:joda-time', diff --git a/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/ByteBufferUtils.scala b/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/ByteBufferUtils.scala index 346c7ac322..59ccaffdf4 100644 --- a/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/ByteBufferUtils.scala +++ b/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/ByteBufferUtils.scala @@ -7,8 +7,16 @@ import java.nio.ByteBuffer private[finatra] object ByteBufferUtils extends Logging { + /** + * Append a [[Buf]] to a [[ByteBuffer]] + * @param byteBuffer [[ByteBuffer]] to which to append + * @param buf [[Buf]] to append + * @param position Sets the underlying buffer's position. If the mark is defined and larger than the + * new position then it is discarded. + * @return Owned [[ByteBuffer]] with the appended [[Buf]] at the given position + */ //TODO: Optimize/Refactor - def append(byteBuffer: ByteBuffer, buf: Buf): ByteBuffer = { + def append(byteBuffer: ByteBuffer, buf: Buf, position: Int): ByteBuffer = { val byteBufferBuf = { val byteBufferCopy = byteBuffer.duplicate() byteBufferCopy.position(0) @@ -16,7 +24,9 @@ private[finatra] object ByteBufferUtils extends Logging { } val combinedBufs = byteBufferBuf.concat(buf) - Buf.ByteBuffer.Shared.extract(combinedBufs) + val result = Buf.ByteBuffer.Shared.extract(combinedBufs) + result.position(position) + result } def debugBuffer(byteBuffer: ByteBuffer) = { diff --git a/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/JsonArrayChunker.scala b/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/JsonArrayChunker.scala index 3a889b78fd..35f3deddbb 100644 --- a/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/JsonArrayChunker.scala +++ b/jackson/src/main/scala/com/twitter/finatra/json/internal/streaming/JsonArrayChunker.scala @@ -14,25 +14,28 @@ private[finatra] class JsonArrayChunker extends Logging { private[finatra] var parsingState: ParsingState = Normal private[finatra] var done = false private[finatra] var openBraces = 0 + private[finatra] var position = 0 private var byteBuffer = ByteBuffer.allocate(0) /* Public */ def decode(inputBuf: Buf): Seq[Buf] = { assertDecode(inputBuf) - byteBuffer = ByteBufferUtils.append(byteBuffer, inputBuf) + byteBuffer = ByteBufferUtils.append(byteBuffer, inputBuf, position) val result = ArrayBuffer[Buf]() while (byteBuffer.hasRemaining) { ByteBufferUtils.debugBuffer(byteBuffer) val currByte = byteBuffer.get + position = byteBuffer.position - if (!arrayFound && currByte == '[') { + if (!arrayFound && currByte == '[' && openBraces == 0) { debug("ArrayFound. Openbraces = 1") parsingState = InsideArray - openBraces = 1 + openBraces += 1 byteBuffer = byteBuffer.slice() + position = 0 } else if (!arrayFound && Character.isWhitespace(currByte.toChar)) { debug("Skip space") } else { @@ -69,7 +72,7 @@ private[finatra] class JsonArrayChunker extends Logging { parsingState = InsideString } // If the double quote wasn't escaped then this is the end of a string. - else if (in.get(in.position - 1) != '\\') { + else if (in.get(in.position - 2) != '\\') { debug("State = Parsing") parsingState = Normal } @@ -84,6 +87,7 @@ private[finatra] class JsonArrayChunker extends Logging { val copyBuf = Buf.ByteBuffer.Shared(copy) byteBuffer = byteBuffer.slice() + position = 0 debug("Extract result " + copyBuf.utf8str) copyBuf } diff --git a/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/ByteBufferUtilsTest.scala b/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/ByteBufferUtilsTest.scala index dd81a8a74c..09f8974cd7 100644 --- a/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/ByteBufferUtilsTest.scala +++ b/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/ByteBufferUtilsTest.scala @@ -10,7 +10,7 @@ class ByteBufferUtilsTest extends Test { test("ByteBufferUtils.append") { val input = Buf.ByteBuffer.Shared.extract(Buf.Utf8("1")) input.get() - val byteBufferResult = ByteBufferUtils.append(input, Buf.Utf8(",2")) + val byteBufferResult = ByteBufferUtils.append(input, Buf.Utf8(",2"), position = 0) byteBufferResult.utf8str should equal("1,2") } diff --git a/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/StreamingTest.scala b/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/StreamingTest.scala index 84542e1f48..9c248b78d7 100644 --- a/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/StreamingTest.scala +++ b/jackson/src/test/scala/com/twitter/finatra/json/tests/internal/streaming/StreamingTest.scala @@ -4,6 +4,7 @@ import com.twitter.concurrent.AsyncStream import com.twitter.finagle.http.{Method, Request} import com.twitter.finatra.json.FinatraObjectMapper import com.twitter.finatra.json.internal.streaming.JsonStreamParser +import com.twitter.finatra.json.tests.internal.{CaseClassWithSeqBooleans, FooClass} import com.twitter.inject.Test import com.twitter.io.Buf import com.twitter.util.Await @@ -42,6 +43,47 @@ class StreamingTest extends Test { ) } + test("bufs to json with some bigger objects") { + assertParsedSimpleObjects( + AsyncStream(Buf.Utf8("""[{ "id":"John" }"""), + Buf.Utf8(""",{ "id":"Tom" },{ "id":"An" },"""), + Buf.Utf8("""{ "id":"Jean" }]""")), + expectedInputStr = """[{ "id":"John" },{ "id":"Tom" },{ "id":"An" },{ "id":"Jean" }]""", + expected = AsyncStream(FooClass("John"), FooClass("Tom"), FooClass("An"), FooClass("Jean")) + ) + } + + test("bufs to json with some complex objects") { + assertParsedComplexObjects( + AsyncStream(Buf.Utf8("""[{ "foos":[true,false,true] }"""), + Buf.Utf8(""",{ "foos": [true,false,true] },"""), + Buf.Utf8("""{ "foos":[false] }]""")), + expectedInputStr = """[{ "foos":[true,false,true] },{ "foos": [true,false,true] },{ "foos":[false] }]""", + expected = AsyncStream(CaseClassWithSeqBooleans(Seq(true,false,true)), + CaseClassWithSeqBooleans(Seq(true,false,true)), CaseClassWithSeqBooleans(Seq(false))) + ) + } + + test("bufs to json with some bigger objects and an escape character") { + assertParsedSimpleObjects( + AsyncStream(Buf.Utf8("""[{ "id":"John" }"""), + Buf.Utf8(""",{ "id":"Tom" },{ "id""""), + Buf.Utf8(""":"An" },{ "id":"Jean" }]""")), + expectedInputStr = """[{ "id":"John" },{ "id":"Tom" },{ "id":"An" },{ "id":"Jean" }]""", + expected = AsyncStream(FooClass("John"), FooClass("Tom"), FooClass("An"), FooClass("Jean")) + ) + } + + test("bufs to json with some bigger objects but with json object split over 2 bufs") { + assertParsedSimpleObjects( + AsyncStream(Buf.Utf8("""[{ "id":"John" }"""), + Buf.Utf8(""",{ "id":"Tom" },{ "id""""), + Buf.Utf8(""":"An" },{ "id":"Jean" }]""")), + expectedInputStr = """[{ "id":"John" },{ "id":"Tom" },{ "id":"An" },{ "id":"Jean" }]""", + expected = AsyncStream(FooClass("John"), FooClass("Tom"), FooClass("An"), FooClass("Jean")) + ) + } + test("parse request") { val jsonStr = "[1,2]" val request = Request(Method.Post, "/") @@ -53,7 +95,7 @@ class StreamingTest extends Test { request.writer.close() } - Await.result(parser.parseArray[Int](request.reader).toSeq()) should equal(Seq(1, 2)) + assertFutureValue(parser.parseArray[Int](request.reader).toSeq(), Seq(1, 2)) } private def readString(bufs: AsyncStream[Buf]): String = { @@ -72,6 +114,29 @@ class StreamingTest extends Test { readString(bufs) should equal(expectedInputStr) val parser = new JsonStreamParser(FinatraObjectMapper.create()) - Await.result(parser.parseArray[Int](bufs).toSeq) should equal(Await.result(expected.toSeq())) + assertFuture(parser.parseArray[Int](bufs).toSeq(), expected.toSeq()) } + + private def assertParsedSimpleObjects( + bufs: AsyncStream[Buf], + expectedInputStr: String, + expected: AsyncStream[FooClass] + ): Unit = { + + readString(bufs) should equal(expectedInputStr) + val parser = new JsonStreamParser(FinatraObjectMapper.create()) + assertFuture(parser.parseArray[FooClass](bufs).toSeq(), expected.toSeq()) + } + + private def assertParsedComplexObjects( + bufs: AsyncStream[Buf], + expectedInputStr: String, + expected: AsyncStream[CaseClassWithSeqBooleans] + ): Unit = { + + readString(bufs) should equal(expectedInputStr) + val parser = new JsonStreamParser(FinatraObjectMapper.create()) + assertFuture(parser.parseArray[CaseClassWithSeqBooleans](bufs).toSeq(), expected.toSeq()) + } + } diff --git a/project/build.properties b/project/build.properties index c091b86ca4..94005e587c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 +sbt.version=1.0.0 diff --git a/project/build.sbt b/project/build.sbt new file mode 100644 index 0000000000..b0c386212f --- /dev/null +++ b/project/build.sbt @@ -0,0 +1 @@ +scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-encoding", "utf8") diff --git a/project/plugins.sbt b/project/plugins.sbt index b7063e7373..eca7dfc8fe 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,16 +1,16 @@ resolvers ++= Seq( - Classpaths.sbtPluginSnapshots, Classpaths.sbtPluginReleases, Resolver.sonatypeRepo("snapshots") ) -val releaseVersion = "17.10.0" +val releaseVersion = "17.11.0" addSbtPlugin("com.twitter" % "scrooge-sbt-plugin" % releaseVersion) addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.0") addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC10") +// removed until https://github.com/sbt/sbt/issues/3496 is fixed +// addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.27") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.0") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") diff --git a/pushsite.bash b/pushsite.bash index d00855f22c..39b7479ebf 100755 --- a/pushsite.bash +++ b/pushsite.bash @@ -19,7 +19,7 @@ cd $savedir ./sbt clean echo 'making site...' 1>&2 -./sbt --warn site/make-site +./sbt --warn site/makeSite echo 'copying site to finatra/gh-pages...' 1>&2 cp -r $savedir/doc/target/site/ /tmp/finatra-github/ >/dev/null 2>&1 diff --git a/sbt b/sbt index 657d7c9f1e..5b8af0428c 100755 --- a/sbt +++ b/sbt @@ -1,31 +1,30 @@ #!/bin/bash -sbtver=0.13.15 +sbtver=1.0.3 sbtjar=sbt-launch.jar -sbtsha128=61bfa3f5791325235f6d7cc37a7e7f6bfeb83531 +sbtsha128=f55b2016e6cace9af7ac4a667dc0092572811cfb -sbtrepo="http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/$sbtver/$sbtjar" +sbtrepo="https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch" if [ ! -f $sbtjar ]; then - echo "downloading $PWD/$sbtjar from $sbtrepo" 1>&2 - if ! curl --location --silent --fail --remote-name $sbtrepo > $sbtjar; then + echo "downloading $PWD/$sbtjar" 1>&2 + if ! curl --location --silent --fail --remote-name $sbtrepo/$sbtver/$sbtjar; then exit 1 fi fi checksum=`openssl dgst -sha1 $sbtjar | awk '{ print $2 }'` if [ "$checksum" != $sbtsha128 ]; then - echo "[error] Bad $PWD/$sbtjar. Delete $PWD/$sbtjar and run $0 again." + echo "bad $PWD/$sbtjar. delete $PWD/$sbtjar and run $0 again." exit 1 fi -javaVersion=`java -version 2>&1 | grep "java version" | awk '{print $3}' | tr -d \"` - [ -f ~/.sbtconfig ] && . ~/.sbtconfig java -ea \ $SBT_OPTS \ $JAVA_OPTS \ + -Djava.net.preferIPv4Stack=true \ -XX:+AggressiveOpts \ -XX:+UseParNewGC \ -XX:+UseConcMarkSweepGC \ @@ -35,7 +34,10 @@ java -ea \ -XX:SurvivorRatio=128 \ -XX:MaxTenuringThreshold=0 \ -XX:-EliminateAutoBox \ + -Xss8M \ -Xms512M \ - -Xmx1280M \ + -Xmx2G \ -server \ -jar $sbtjar "$@" + +stty echo || true \ No newline at end of file diff --git a/thrift/src/main/scala/BUILD b/thrift/src/main/scala/BUILD index 4f8a8e692d..273b6836df 100644 --- a/thrift/src/main/scala/BUILD +++ b/thrift/src/main/scala/BUILD @@ -34,7 +34,7 @@ scala_library( 'finatra/utils/src/main/java', 'finatra/utils/src/main/scala', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', diff --git a/thrift/src/test/java/BUILD b/thrift/src/test/java/BUILD index f7272140a1..37e382e456 100644 --- a/thrift/src/test/java/BUILD +++ b/thrift/src/test/java/BUILD @@ -1,6 +1,5 @@ junit_tests( dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject/extensions:guice-testlib', @@ -28,7 +27,7 @@ junit_tests( 'finatra/utils/src/main/java', 'finatra/utils/src/main/scala', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala', diff --git a/thrift/src/test/scala/BUILD b/thrift/src/test/scala/BUILD index a429dd065b..e3d0d479b6 100644 --- a/thrift/src/test/scala/BUILD +++ b/thrift/src/test/scala/BUILD @@ -29,7 +29,7 @@ junit_tests( 'finatra/utils/src/main/java', 'finatra/utils/src/main/scala', 'scrooge/scrooge-core/src/main/scala', - 'twitter-server/src/main/scala', + 'twitter-server/server/src/main/scala', 'util/util-app/src/main/scala', 'util/util-core/src/main/scala', 'util/util-lint/src/main/scala:scala', @@ -58,7 +58,7 @@ scala_library(name="test-deps", 'finagle/finagle-thriftmux/src/main/scala', 'finatra/inject/inject-server/src/main/scala', 'finatra/inject/inject-server/src/test/scala:test-deps', - 'twitter-server/src/main/scala:scala', + 'twitter-server/server/src/main/scala:scala', 'util/util-stats/src/main/scala', ], fatal_warnings=True, diff --git a/thrift/src/test/scala/com/twitter/finatra/thrift/EmbeddedThriftServer.scala b/thrift/src/test/scala/com/twitter/finatra/thrift/EmbeddedThriftServer.scala index caaa35d9ba..1ee9e0f31c 100644 --- a/thrift/src/test/scala/com/twitter/finatra/thrift/EmbeddedThriftServer.scala +++ b/thrift/src/test/scala/com/twitter/finatra/thrift/EmbeddedThriftServer.scala @@ -29,8 +29,8 @@ import scala.reflect.runtime.universe._ */ class EmbeddedThriftServer( override val twitterServer: Ports, - flags: Map[String, String] = Map(), - args: Seq[String] = Seq(), + flags: => Map[String, String] = Map(), + args: => Seq[String] = Seq(), waitForWarmup: Boolean = true, stage: Stage = Stage.DEVELOPMENT, useSocksProxy: Boolean = false, diff --git a/utils/src/main/scala/BUILD b/utils/src/main/scala/BUILD index e6cfe4e3f2..a624c2a276 100644 --- a/utils/src/main/scala/BUILD +++ b/utils/src/main/scala/BUILD @@ -5,17 +5,17 @@ scala_library( repo = artifactory, ), dependencies=[ - '3rdparty/jvm/com/fasterxml/jackson:jackson-annotations', '3rdparty/jvm/com/google/inject/extensions:guice-assistedinject', '3rdparty/jvm/com/google/inject/extensions:guice-multibindings', '3rdparty/jvm/com/google/inject:guice', + '3rdparty/jvm/commons-io', '3rdparty/jvm/commons-lang:commons-lang', '3rdparty/jvm/javax/inject:javax.inject', '3rdparty/jvm/joda-time:joda-time', '3rdparty/jvm/net/codingwell:scala-guice', '3rdparty/jvm/org/slf4j:slf4j-api', 'finagle/finagle-core/src/main/scala', - 'finagle/finagle-http/src/main/scala', + 'finatra/inject/inject-app/src/main/scala', 'finatra/inject/inject-core/src/main/scala', 'finatra/inject/inject-slf4j/src/main/scala:scala', 'finatra/inject/inject-utils/src/main/scala', diff --git a/http/src/main/scala/com/twitter/finatra/http/routing/FileResolver.scala b/utils/src/main/scala/com/twitter/finatra/utils/FileResolver.scala similarity index 98% rename from http/src/main/scala/com/twitter/finatra/http/routing/FileResolver.scala rename to utils/src/main/scala/com/twitter/finatra/utils/FileResolver.scala index 022c64cf1a..6c10ea7fa1 100644 --- a/http/src/main/scala/com/twitter/finatra/http/routing/FileResolver.scala +++ b/utils/src/main/scala/com/twitter/finatra/utils/FileResolver.scala @@ -1,4 +1,4 @@ -package com.twitter.finatra.http.routing +package com.twitter.finatra.utils import com.twitter.inject.Logging import com.twitter.inject.annotations.Flag diff --git a/http/src/test/scala/com/twitter/finatra/http/tests/routing/FileResolverTest.scala b/utils/src/test/scala/com/twitter/finatra/tests/utils/FileResolverTest.scala similarity index 85% rename from http/src/test/scala/com/twitter/finatra/http/tests/routing/FileResolverTest.scala rename to utils/src/test/scala/com/twitter/finatra/tests/utils/FileResolverTest.scala index 7840849beb..db3c7465c8 100644 --- a/http/src/test/scala/com/twitter/finatra/http/tests/routing/FileResolverTest.scala +++ b/utils/src/test/scala/com/twitter/finatra/tests/utils/FileResolverTest.scala @@ -1,6 +1,6 @@ package com.twitter.finatra.http.tests.routing -import com.twitter.finatra.http.routing.FileResolver +import com.twitter.finatra.utils.FileResolver import com.twitter.inject.Test class FileResolverTest extends Test {