Skip to content

Commit

Permalink
Upgrade to Scala 2.12 (#6691)
Browse files Browse the repository at this point in the history
* Upgrades various dependencies for 2.12

* Apply Application fixes

* Add mediator workaround

* Add mediator workaround to akka-http-server

* Comment out akka-http scripted tests

* Update dependencies

* Fix Scala 2.12 SAM inference

* Fix ambiguous documentation tests

* Change package.html to relative link
  • Loading branch information
wsargent committed Nov 30, 2016
1 parent d23bc40 commit c9d2b33
Show file tree
Hide file tree
Showing 53 changed files with 363 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
package assets.controllers

import java.io.File
import javax.inject.Inject

import play.api.mvc._

class RangeRequestController extends Controller {
class RangeRequestController @Inject()(c: ControllerComponents) extends AbstractController(c) {

// #range-request
def video(videoId: Long) = Action { implicit request =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import scala.concurrent.{ExecutionContext, Future, TimeoutException}
import org.specs2.execute.AsResult

class ThreadPoolsSpec extends PlaySpecification {
import scala.concurrent.ExecutionContext.Implicits.global

"Play's thread pools" should {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ play.http.filters = "filters.MyFilters"

## Configuring the security headers

Scaladoc is available in the [play.filters.headers](api/scala/play/filters/headers/package.html) package.
Scaladoc is available in the [play.filters.headers](api/scala/play/filters/headers/) package.

The filter will set headers in the HTTP response automatically. The settings can be configured through the following settings in `application.conf`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package detailedtopics.configuration.gzipencoding

import akka.stream.ActorMaterializer
import play.api.test._
import detailedtopics.configuration.gzipencoding.CustomFilters

class GzipEncoding extends PlaySpecification {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import play.filters.gzip.GzipFilter;
import play.filters.gzip.GzipFilterConfig;
import play.http.HttpFilters;
import play.mvc.Http;
import play.mvc.Result;

import javax.inject.Inject;
import java.util.function.BiFunction;

public class CustomFilters implements HttpFilters {

Expand All @@ -18,8 +21,9 @@ public class CustomFilters implements HttpFilters {
@Inject
public CustomFilters(Materializer materializer) {
//#gzip-filter
GzipFilterConfig gzipFilterConfig = new GzipFilterConfig();
GzipFilter gzipFilter = new GzipFilter(
new GzipFilterConfig().withShouldGzip((req, res) ->
gzipFilterConfig.withShouldGzip((BiFunction<Http.RequestHeader, Result, Object>) (req, res) ->
res.body().contentType().orElse("").startsWith("text/html")
), materializer
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Play provides a DSL for defining embedded routers called the *String Interpolati

Sird is based on a string interpolated extractor object. Just as Scala supports interpolating parameters into strings for building strings (and any object for that matter), such as `s"Hello $to"`, the same mechanism can also be used to extract parameters out of strings, for example in case statements.

The DSL lives in the [`play.api.routing.sird`](api/scala/play/api/routing/sird/package.html) package. Typically, you will want to import this package, as well as a few other packages:
The DSL lives in the [`play.api.routing.sird`](api/scala/play/api/routing/sird/) package. Typically, you will want to import this package, as well as a few other packages:

@[imports](code/ScalaSirdRouter.scala)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import org.specs2.runner.JUnitRunner

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.test._
import java.io.File

Expand Down Expand Up @@ -43,7 +42,7 @@ class ScalaAkkaSpec extends PlaySpecification {
import play.api.mvc.Results._
import actors.HelloActor.SayHello


import scala.concurrent.ExecutionContext.Implicits.global
//#ask
import scala.concurrent.duration._
import akka.pattern.ask
Expand Down Expand Up @@ -79,6 +78,7 @@ class ScalaAkkaSpec extends PlaySpecification {
import akka.pattern.ask
implicit val timeout: Timeout = 5.seconds

import scala.concurrent.ExecutionContext.Implicits.global
val actor = app.injector.instanceOf(bind[ActorRef].qualifiedWith("parent-actor"))
val futureConfig = for {
child <- (actor ? actors.ParentActor.GetChild("my.config")).mapTo[ActorRef]
Expand All @@ -95,6 +95,7 @@ class ScalaAkkaSpec extends PlaySpecification {
//#schedule-actor
import scala.concurrent.duration._

import scala.concurrent.ExecutionContext.Implicits.global
val cancellable = system.scheduler.schedule(
0.microseconds, 300.microseconds, testActor, "tick")
//#schedule-actor
Expand All @@ -104,6 +105,7 @@ class ScalaAkkaSpec extends PlaySpecification {
"actor scheduler" in withActorSystem { system =>
val file = new File("/tmp/nofile")
file.mkdirs()
import scala.concurrent.ExecutionContext.Implicits.global
//#schedule-callback
system.scheduler.scheduleOnce(10.milliseconds) {
file.delete()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--- Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com> -->
# Using Custom Validations

The [validation package](api/scala/play/api/data/validation/package.html) allows you to create ad-hoc constraints using the `verifying` method. However, Play gives you the option of creating your own custom constraints, using the [`Constraint`](api/scala/play/api/data/validation/Constraint.html) case class.
The [validation package](api/scala/play/api/data/validation/) allows you to create ad-hoc constraints using the `verifying` method. However, Play gives you the option of creating your own custom constraints, using the [`Constraint`](api/scala/play/api/data/validation/Constraint.html) case class.

Here, we'll implement a simple password strength constraint that uses regular expressions to check the password is not all letters or all numbers. A [`Constraint`](api/scala/play/api/data/validation/Constraint.html) takes a function which returns a [`ValidationResult`](api/scala/play/api/data/validation/ValidationResult.html), and we use that function to return the results of the password check:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ The out of the box constraints are defined on the [Forms object](api/scala/play/

### Defining ad-hoc constraints

You can define your own ad-hoc constraints on the case classes using the [validation package](api/scala/play/api/data/validation/package.html).
You can define your own ad-hoc constraints on the case classes using the [validation package](api/scala/play/api/data/validation/).

@[userForm-constraints](code/ScalaForms.scala)

Expand Down Expand Up @@ -130,7 +130,7 @@ The first thing is to be able to create the [form tag](api/scala/views/html/help

@[form-user](code/scalaguide/forms/scalaforms/views/user.scala.html)

You can find several input helpers in the [`views.html.helper`](api/scala/views/html/helper/package.html) package. You feed them with a form field, and they display the corresponding HTML input, setting the value, constraints and displaying errors when a form binding fails.
You can find several input helpers in the [`views.html.helper`](api/scala/views/html/helper/) package. You feed them with a form field, and they display the corresponding HTML input, setting the value, constraints and displaying errors when a form binding fails.

> **Note:** You can use `@import helper._` in the template to avoid prefixing helpers with `@helper.`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ class ScalaActionsCompositionSpec extends Specification with Controller {
}
//#item-action-use

import scala.concurrent.ExecutionContext.Implicits.global
testAction(tagItem("foo", "bar"), expectedResponse = FORBIDDEN)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import org.specs2.execute.AsResult

@RunWith(classOf[JUnitRunner])
class ScalaBodyParsersSpec extends Specification with Controller {
import scala.concurrent.ExecutionContext.Implicits.global

def helloRequest = FakeRequest("POST", "/").withJsonBody(Json.obj("name" -> "foo"))

"A scala body parser" should {

"parse request as json" in {
import scala.concurrent.ExecutionContext.Implicits.global
//#access-json-body
def save = Action { request =>
val body: AnyContent = request.body
Expand Down Expand Up @@ -130,7 +130,7 @@ import org.specs2.execute.AsResult
}

"parse the body as csv" in new WithApplication() {

import scala.concurrent.ExecutionContext.Implicits.global
//#csv
import play.api.mvc._
import play.api.libs.streams._
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--- Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com> -->
# JSON basics

Modern web applications often need to parse and generate data in the JSON (JavaScript Object Notation) format. Play supports this via its [JSON library](api/scala/play/api/libs/json/package.html).
Modern web applications often need to parse and generate data in the JSON (JavaScript Object Notation) format. Play supports this via its [JSON library](api/scala/play/api/libs/json/).

JSON is a lightweight data-interchange format and looks like this:

Expand All @@ -28,7 +28,7 @@ JSON is a lightweight data-interchange format and looks like this:
## The Play JSON library

The [`play.api.libs.json`](api/scala/play/api/libs/json/package.html) package contains data structures for representing JSON data and utilities for converting between these data structures and other data representations. Some of the features of this package are:
The [`play.api.libs.json`](api/scala/play/api/libs/json/) package contains data structures for representing JSON data and utilities for converting between these data structures and other data representations. Some of the features of this package are:

- [[Automatic conversion|ScalaJsonAutomated]] to and from case classes with minimal boilerplate. If you want to get up and running quickly with minimal code, this is probably the place to start.
- [[Custom validation|ScalaJsonCombinators#Validation-with-Reads]] while parsing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The examples on this page will use this `JsValue` structure and corresponding mo

@[jspath-define](code/ScalaJsonCombinatorsSpec.scala)

The [`play.api.libs.json`](api/scala/play/api/libs/json/package.html) package defines an alias for `JsPath`: `__` (double underscore). You can use this if you prefer:
The [`play.api.libs.json`](api/scala/play/api/libs/json/) package defines an alias for `JsPath`: `__` (double underscore). You can use this if you prefer:

@[jspath-define-alias](code/ScalaJsonCombinatorsSpec.scala)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--- Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com> -->
# Writing functional tests with specs2

Play provides a number of classes and convenience methods that assist with functional testing. Most of these can be found either in the [`play.api.test`](api/scala/play/api/test/package.html) package or in the [`Helpers`](api/scala/play/api/test/Helpers$.html) object.
Play provides a number of classes and convenience methods that assist with functional testing. Most of these can be found either in the [`play.api.test`](api/scala/play/api/test/) package or in the [`Helpers`](api/scala/play/api/test/Helpers$.html) object.

You can add these methods and classes by importing the following:

Expand Down
2 changes: 1 addition & 1 deletion documentation/manual/working/scalaGuide/main/ws/ScalaWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--- Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com> -->
# The Play WS API

Sometimes we would like to call other HTTP services from within a Play application. Play supports this via its [WS library](api/scala/play/api/libs/ws/package.html), which provides a way to make asynchronous HTTP calls through a WSClient instance.
Sometimes we would like to call other HTTP services from within a Play application. Play supports this via its [WS library](api/scala/play/api/libs/ws/), which provides a way to make asynchronous HTTP calls through a WSClient instance.

There are two important parts to using the WSClient: making a request, and processing the response. We'll discuss how to make both GET and POST HTTP requests first, and then show how to process the response from WSClient. Finally, we'll discuss some common use cases.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ package scalaguide.ws.scalaoauth

import play.api.test._

import scala.concurrent.ExecutionContext

//#dependency
import javax.inject.Inject
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import play.api.libs.oauth._
import play.api.libs.ws._

class HomeController @Inject()(wsClient:WSClient) extends Controller {

}
class HomeController @Inject()(val wsClient: WSClient,
c: ControllerComponents)
(implicit val ec: ExecutionContext)
extends AbstractController(c)
//#dependency


Expand All @@ -30,70 +29,67 @@ object routes {
}
}


class ScalaOAuthSpec extends PlaySpecification {

"Scala OAuth" should {
"be injectable" in new WithApplication() {
app.injector.instanceOf[Application] must beAnInstanceOf[Application]
}
}

def wsClient: WSClient = null

import play.api.mvc.Results._
//#flow
val KEY = ConsumerKey("xxxxx", "xxxxx")

val oauth = OAuth(ServiceInfo(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize", KEY),
true)

def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}
"be injectable" in new WithApplication() with Injecting {
val controller = new HomeController(inject[WSClient], inject[ControllerComponents])(inject[ExecutionContext]) {
//#flow
val KEY = ConsumerKey("xxxxx", "xxxxx")

val oauth = OAuth(ServiceInfo(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize", KEY),
true)

def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}

def authenticate = Action { request =>
request.getQueryString("oauth_verifier").map { verifier =>
val tokenPair = sessionTokenPair(request).get
// We got the verifier; now get the access token, store it and back to index
oauth.retrieveAccessToken(tokenPair, verifier) match {
case Right(t) => {
// We received the authorized tokens in the OAuth object - store it before we proceed
Redirect(routes.Application.index).withSession("token" -> t.token, "secret" -> t.secret)
def authenticate = Action { request: Request[AnyContent] =>
request.getQueryString("oauth_verifier").map { verifier =>
val tokenPair = sessionTokenPair(request).get
// We got the verifier; now get the access token, store it and back to index
oauth.retrieveAccessToken(tokenPair, verifier) match {
case Right(t) => {
// We received the authorized tokens in the OAuth object - store it before we proceed
Redirect(routes.Application.index).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
}
}.getOrElse(
oauth.retrieveRequestToken("https://localhost:9000/auth") match {
case Right(t) => {
// We received the unauthorized tokens in the OAuth object - store it before we proceed
Redirect(oauth.redirectUrl(t.token)).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
})
}
case Left(e) => throw e
}
}.getOrElse(
oauth.retrieveRequestToken("https://localhost:9000/auth") match {
case Right(t) => {
// We received the unauthorized tokens in the OAuth object - store it before we proceed
Redirect(oauth.redirectUrl(t.token)).withSession("token" -> t.token, "secret" -> t.secret)
//#flow

//#extended
def timeline = Action.async { implicit request: Request[AnyContent] =>
sessionTokenPair match {
case Some(credentials) => {
wsClient.url("https://api.twitter.com/1.1/statuses/home_timeline.json")
.sign(OAuthCalculator(KEY, credentials))
.get
.map(result => Ok(result.json))
}
case _ => Future.successful(Redirect(routes.Application.authenticate))
}
}
case Left(e) => throw e
})
}
//#flow

//#extended
def timeline = Action.async { implicit request =>
sessionTokenPair match {
case Some(credentials) => {
wsClient.url("https://api.twitter.com/1.1/statuses/home_timeline.json")
.sign(OAuthCalculator(KEY, credentials))
.get
.map(result => Ok(result.json))
//#extended
}
case _ => Future.successful(Redirect(routes.Application.authenticate))
controller must beAnInstanceOf[HomeController]
}
}
//#extended

}
Loading

0 comments on commit c9d2b33

Please sign in to comment.