From d8922c406f3c7d13add6c93fea92be6446fd6638 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:17:35 +0100 Subject: [PATCH 01/20] Switch to Pekko --- app/config/Filters.scala | 2 +- app/controllers/FaciaContentApiProxy.scala | 2 +- app/filters/LoggingFilter.scala | 2 +- app/metrics/metrics.scala | 2 +- app/switchboard/Switchboard.scala | 3 ++- conf/application.conf | 4 ++-- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/config/Filters.scala b/app/config/Filters.scala index 5928e99e9f4..d75dab8a508 100644 --- a/app/config/Filters.scala +++ b/app/config/Filters.scala @@ -1,6 +1,6 @@ package config -import akka.stream.Materializer +import org.apache.pekko.stream.Materializer import play.api.mvc.ResponseHeader import play.filters.gzip.GzipFilter diff --git a/app/controllers/FaciaContentApiProxy.scala b/app/controllers/FaciaContentApiProxy.scala index 82094722639..6e8bcdd0255 100644 --- a/app/controllers/FaciaContentApiProxy.scala +++ b/app/controllers/FaciaContentApiProxy.scala @@ -18,7 +18,7 @@ import scala.concurrent.ExecutionContext class FaciaContentApiProxy(capi: Capi, val deps: BaseFaciaControllerComponents)(implicit ec: ExecutionContext) extends BaseFaciaController(deps) with Logging { - implicit val futures = new play.api.libs.concurrent.DefaultFutures(akka.actor.ActorSystem()) + implicit val futures = new play.api.libs.concurrent.DefaultFutures(org.apache.pekko.actor.ActorSystem()) implicit class string2encodings(s: String) { lazy val urlEncoded = URLEncoder.encode(s, "utf-8") } diff --git a/app/filters/LoggingFilter.scala b/app/filters/LoggingFilter.scala index b790f392e87..413e414258b 100644 --- a/app/filters/LoggingFilter.scala +++ b/app/filters/LoggingFilter.scala @@ -2,7 +2,7 @@ package filters import javax.inject.Inject import scala.jdk.CollectionConverters._ -import akka.stream.Materializer +import org.apache.pekko.stream.Materializer import play.api.MarkerContext import play.api.mvc._ import scala.concurrent.{ExecutionContext, Future} diff --git a/app/metrics/metrics.scala b/app/metrics/metrics.scala index aa48790a8e7..8f19abb0050 100644 --- a/app/metrics/metrics.scala +++ b/app/metrics/metrics.scala @@ -4,7 +4,7 @@ import java.io.File import java.lang.management.{GarbageCollectorMXBean, ManagementFactory} import java.util.concurrent.atomic.AtomicLong -import akka.actor.Scheduler +import org.apache.pekko.actor.Scheduler import com.amazonaws.services.cloudwatch.model.{Dimension, StandardUnit} import logging.Logging diff --git a/app/switchboard/Switchboard.scala b/app/switchboard/Switchboard.scala index fe50b7d20ee..3e8e6866002 100644 --- a/app/switchboard/Switchboard.scala +++ b/app/switchboard/Switchboard.scala @@ -1,6 +1,7 @@ package switchboard -import akka.actor.Scheduler + +import org.apache.pekko.actor.Scheduler import com.amazonaws.auth.AWSCredentialsProvider import logging.Logging diff --git a/conf/application.conf b/conf/application.conf index 81d7226647f..208f1856a7b 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -1,5 +1,5 @@ -akka { - akka.loggers = ["akka.event.Logging$DefaultLogger", "akka.event.slf4j.Slf4jLogger"] +pekko { + pekko.loggers = ["org.apache.pekko.event.Logging$DefaultLogger", "org.apache.pekko.event.slf4j.Slf4jLogger"] loglevel = WARNING actor { default-dispatcher = { From 422f32c9626a5e71fd258520feebfa8d051886ee Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:18:02 +0100 Subject: [PATCH 02/20] Switching to Pekko Hopefully this isn't needed - it is a Dev mode only setting --- build.sbt | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.sbt b/build.sbt index 90066ec0776..7002336f9eb 100644 --- a/build.sbt +++ b/build.sbt @@ -56,8 +56,6 @@ resolvers ++= Seq( ) -PlayKeys.devSettings := Seq("play.akka.dev-mode.akka.http.parsing.max-uri-length" -> "20480") - libraryDependencies ++= Seq( ws, filters, From abba0a8886b8e78152028ac4bf61dcc4f8941ace Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 7 May 2024 12:39:05 +0100 Subject: [PATCH 03/20] Bump ScalikeJDBC To version which supports Play 3.0 --- .../editions/db/CollectionsQueries.scala | 14 ++++----- app/services/editions/db/FrontsQueries.scala | 10 +++---- app/services/editions/db/IssueQueries.scala | 30 +++++++++---------- build.sbt | 6 ++-- .../db/EditionsDBEvolutionsTest.scala | 6 ++-- .../services/editions/db/EditionsDBTest.scala | 12 ++++---- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/app/services/editions/db/CollectionsQueries.scala b/app/services/editions/db/CollectionsQueries.scala index da1ed592db3..10d2f815053 100644 --- a/app/services/editions/db/CollectionsQueries.scala +++ b/app/services/editions/db/CollectionsQueries.scala @@ -64,8 +64,8 @@ trait CollectionsQueries { val contentPrefillQueryTimeWindow = CapiQueryTimeWindow(timeWinStart, timeWinEnd) - (date, edition, zone, CapiPrefillQuery(rs.string("prefill"), pathType), contentPrefillQueryTimeWindow, rs.string("id")) - }.list().apply() + (date, edition, zone, CapiPrefillQuery(rs.string("prefill"), pathType), contentPrefillQueryTimeWindow, rs.string("page_code")) + }.list.apply() rows.headOption.map { case (issueDate, edition, zone, prefillQueryUrlSegments, contentPrefillQueryTimeWindow, _) => PrefillUpdate(issueDate, edition, zone, prefillQueryUrlSegments, contentPrefillQueryTimeWindow, rows.map(_._6)) @@ -81,7 +81,7 @@ trait CollectionsQueries { updated_by = ${collection.updatedBy}, updated_email = ${collection.updatedEmail} WHERE id = ${collection.id} - """.execute().apply() + """.execute.apply() val rows = fetchCollectionsSql(where = sqls"collections.id = ${collection.id}").apply() @@ -102,12 +102,12 @@ trait CollectionsQueries { updated_by = ${collection.updatedBy}, updated_email = ${collection.updatedEmail} WHERE id = ${collection.id} - """.execute().apply() + """.execute.apply() // At the moment we don't do partial updates so simply delete all of them and reinsert. sql""" DELETE FROM cards WHERE collection_id = ${collection.id} - """.execute().apply() + """.execute.apply() collection.items.zipWithIndex.foreach { case (card, index) => val addedOn = EditionsDB.dateTimeFromMillis(card.addedOn) @@ -119,7 +119,7 @@ trait CollectionsQueries { added_on, metadata ) VALUES (${collection.id}, ${card.id}, $index, $addedOn, ${card.metadata.map(m => Json.toJson(m).toString)}::JSONB) - """.execute().apply() + """.execute.apply() } val rows = fetchCollectionsSql(where = sqls"collections.id = ${collection.id}").apply() @@ -168,7 +168,7 @@ trait CollectionsQueries { EditionsCollection.fromRow(rs), DbEditionsCard.fromRowOpt(rs, "cards_") ) - }.toList() + }.toList } private def convertRowsToCollections(rows: List[GetCollectionsRow]): List[EditionsCollection] = { diff --git a/app/services/editions/db/FrontsQueries.scala b/app/services/editions/db/FrontsQueries.scala index c2ca85e1f68..21035a54f06 100644 --- a/app/services/editions/db/FrontsQueries.scala +++ b/app/services/editions/db/FrontsQueries.scala @@ -12,7 +12,7 @@ trait FrontsQueries extends Logging { UPDATE fronts SET metadata = ${updatedMetadata.toPGobject} WHERE id = $id - """.execute().apply() + """.execute.apply() sql""" SELECT metadata FROM fronts WHERE id = $id @@ -21,7 +21,7 @@ trait FrontsQueries extends Logging { // Throw if we can't parse the metadata to signal to the user that something is broken Json.parse(metadataString).validate[EditionsFrontMetadata].get } - }.single().apply().flatten + }.single.apply().flatten } def getFrontMetadata(id: String): EditionsFrontMetadata = DB localTx { implicit session => @@ -35,7 +35,7 @@ trait FrontsQueries extends Logging { case "" => "{}" case s:String => s } - }).single().apply().get + }).single.apply().get Json.fromJson[EditionsFrontMetadata](Json.parse(rawJson)).get } @@ -46,13 +46,13 @@ trait FrontsQueries extends Logging { UPDATE fronts SET is_hidden = $isHidden WHERE id = $id AND is_special = TRUE - """.execute().apply() + """.execute.apply() val newState = sql""" SELECT is_hidden, is_special FROM fronts WHERE id = $id """.map { rs => (rs.boolean("is_hidden"), rs.boolean("is_special")) - }.single().apply() + }.single.apply() newState.map { case (isHidden, isSpecial) => if (!isSpecial) logger.warn(s"Tried to update hidden state on front $id which is not a special front") diff --git a/app/services/editions/db/IssueQueries.scala b/app/services/editions/db/IssueQueries.scala index 1d9d8e609ae..f00dba73b9b 100644 --- a/app/services/editions/db/IssueQueries.scala +++ b/app/services/editions/db/IssueQueries.scala @@ -38,7 +38,7 @@ trait IssueQueries extends Logging { created_email ) VALUES (${edition.entryName}, ${issueSkeleton.issueDate}, ${issueSkeleton.zoneId.toString}, $truncatedNow, $userName, ${user.email}) RETURNING id; - """.map(_.string("id")).single().apply().get + """.map(_.string("id")).single.apply().get issueSkeleton.fronts.zipWithIndex.foreach { case (front, fIndex) => val frontId = @@ -52,7 +52,7 @@ trait IssueQueries extends Logging { is_special ) VALUES (${issueId}, ${fIndex}, ${front.name}, ${front.hidden}, ${front.metadata()}, ${front.isSpecial}) RETURNING id; - """.map(_.string("id")).single().apply().get + """.map(_.string("id")).single.apply().get import contentPrefillTimeWindow.{fromDate, toDate} @@ -87,7 +87,7 @@ trait IssueQueries extends Logging { , ${user.email} ) RETURNING id; - """.map(_.string("id")).single().apply().get + """.map(_.string("id")).single.apply().get collection.items.zipWithIndex.foreach { case (card, tIndex) => sql""" @@ -98,7 +98,7 @@ trait IssueQueries extends Logging { added_on, metadata ) VALUES ($collectionId, ${card.id}, $tIndex, $truncatedNow, ${Json.toJson(card.metadata).toString}::JSONB) - """.execute().apply() + """.execute.apply() } } } @@ -121,7 +121,7 @@ trait IssueQueries extends Logging { launched_email FROM edition_issues WHERE issue_date BETWEEN $dateFrom AND $dateTo AND name = ${edition.entryName} - """.map(EditionsIssue.fromRow(_)).list().apply() + """.map(EditionsIssue.fromRow(_)).list.apply() } def getIssueIdFromCollectionId(collectionId: String): Option[String] = DB readOnly { implicit session => @@ -133,7 +133,7 @@ trait IssueQueries extends Logging { WHERE collections.id = $collectionId """.map { rs => rs.string("id") - }.toOption().apply() + }.toOption.apply() } def getIssue(id: String): Option[EditionsIssue] = DB readOnly { implicit session => @@ -202,7 +202,7 @@ trait IssueQueries extends Logging { DbEditionsCollection.fromRowOpt(rs, "collections_"), DbEditionsCard.fromRowOpt(rs, "cards_")) } - .list() + .list .apply() val fronts: List[EditionsFront] = rows @@ -249,7 +249,7 @@ trait IssueQueries extends Logging { WHERE edition_issues.id = $id """ .map(rs => EditionsIssue.fromRow(rs)) - .single() + .single .apply() } @@ -267,7 +267,7 @@ trait IssueQueries extends Logging { launched_by = $userName, launched_email = ${user.email} WHERE id = $issueId - """.execute().apply() + """.execute.apply() sql""" INSERT INTO issue_versions ( @@ -283,7 +283,7 @@ trait IssueQueries extends Logging { , $userName , ${user.email} ); - """.execute().apply() + """.execute.apply() sql""" INSERT INTO issue_versions_events ( @@ -296,14 +296,14 @@ trait IssueQueries extends Logging { , ${IssueVersionStatus.Started.toString} ) RETURNING version_id; - """.map(_.string("version_id")).single().apply().get + """.map(_.string("version_id")).single.apply().get } def deleteIssue(issueId: String) = DB localTx { implicit session => sql""" DELETE FROM edition_issues WHERE id = $issueId - """.execute().apply() + """.execute.apply() } @@ -318,7 +318,7 @@ trait IssueQueries extends Logging { WHERE v.issue_id = $issueId AND e.status = ${IssueVersionStatus.Proofed.toString} """.map(rs => rs.string("version_id")) - .list() + .list .apply() .headOption @@ -343,7 +343,7 @@ trait IssueQueries extends Logging { WHERE v.issue_id = $issueId ORDER BY launched_on DESC """.map(rs => Row(IssueVersion.fromRow(rs), IssueVersionEvent.fromRow(rs))) - .list() + .list .apply() (rows.groupBy(_.version) map { @@ -369,7 +369,7 @@ trait IssueQueries extends Logging { , ${event.status.toString} , ${event.message} ); - """.execute().apply() + """.execute.apply() } match { case Success(_) => { logger.info(s"successfully inserted issue version event message:${event.message}")(event.toLogMarker) diff --git a/build.sbt b/build.sbt index 7002336f9eb..c863c7b9766 100644 --- a/build.sbt +++ b/build.sbt @@ -91,9 +91,9 @@ libraryDependencies ++= Seq( "ai.x" %% "play-json-extensions" % "0.40.2", "org.postgresql" % "postgresql" % "42.3.9", - "org.scalikejdbc" %% "scalikejdbc" % "3.3.5", - "org.scalikejdbc" %% "scalikejdbc-config" % "3.3.5", - "org.scalikejdbc" %% "scalikejdbc-play-initializer" % "2.8.0-scalikejdbc-3.5", + "org.scalikejdbc" %% "scalikejdbc" % "4.2.0", + "org.scalikejdbc" %% "scalikejdbc-config" % "4.2.1", + "org.scalikejdbc" %% "scalikejdbc-play-initializer" % "3.0.0-scalikejdbc-4.2", "io.circe" %% "circe-core" % circeVersion, "io.circe" %% "circe-generic" % circeVersion, diff --git a/test/services/editions/db/EditionsDBEvolutionsTest.scala b/test/services/editions/db/EditionsDBEvolutionsTest.scala index 003a3e0489c..8ff0d6db71d 100644 --- a/test/services/editions/db/EditionsDBEvolutionsTest.scala +++ b/test/services/editions/db/EditionsDBEvolutionsTest.scala @@ -32,7 +32,7 @@ class EditionsDBEvolutionsTest extends FreeSpec with Matchers with EditionsDBSer created_email ) VALUES ('test-edition', $issueDate, ${zoneId.toString}, $truncatedNow, ${user.username}, ${user.email}) RETURNING id; - """.map(_.string("id")).single().apply().get + """.map(_.string("id")).single.apply().get } } @@ -40,7 +40,7 @@ class EditionsDBEvolutionsTest extends FreeSpec with Matchers with EditionsDBSer DB localTx { implicit session => sql""" SELECT issue_date FROM edition_issues WHERE id = $id - """.map(_.date("issue_date")).single().apply().get + """.map(_.date("issue_date")).single.apply().get } } @@ -48,7 +48,7 @@ class EditionsDBEvolutionsTest extends FreeSpec with Matchers with EditionsDBSer DB localTx { implicit session => sql""" SELECT issue_date FROM edition_issues WHERE id = $id - """.map(_.offsetDateTime("issue_date")).single().apply().get + """.map(_.offsetDateTime("issue_date")).single.apply().get } } diff --git a/test/services/editions/db/EditionsDBTest.scala b/test/services/editions/db/EditionsDBTest.scala index 185f6ba5a3e..68823524430 100644 --- a/test/services/editions/db/EditionsDBTest.scala +++ b/test/services/editions/db/EditionsDBTest.scala @@ -472,15 +472,15 @@ class EditionsDBTest extends FreeSpec with Matchers with EditionsDBService with val collectionId = collectionIds.head (DB localTx { implicit session => - sql"""SELECT id from fronts WHERE issue_id = ${dbIssue.id}""".map(_.string("id")).single().apply() + sql"""SELECT id from fronts WHERE issue_id = ${dbIssue.id}""".map(_.string("id")).single.apply() }) shouldBe Some(frontId) (DB localTx { implicit session => - sql"""SELECT id from collections WHERE front_id = $frontId""".map(_.string("id")).single().apply() + sql"""SELECT id from collections WHERE front_id = $frontId""".map(_.string("id")).single.apply() }) shouldBe Some(collectionId) (DB localTx { implicit session => - sql"""SELECT id from cards WHERE collection_id = $collectionId""".map(_.string("id")).list().apply() + sql"""SELECT id from cards WHERE collection_id = $collectionId""".map(_.string("id")).list.apply() }).length shouldBe 2 editionsDB.deleteIssue(dbIssue.id) @@ -488,15 +488,15 @@ class EditionsDBTest extends FreeSpec with Matchers with EditionsDBService with // ensure an issue deletion performs a cascading delete (DB localTx { implicit session => - sql"""SELECT id from fronts WHERE id = $frontId""".map(_.string("id")).single().apply() + sql"""SELECT id from fronts WHERE id = $frontId""".map(_.string("id")).single.apply() }) should be (DB localTx { implicit session => - sql"""SELECT id from collections WHERE front_id = $frontId""".map(_.string("id")).single().apply() + sql"""SELECT id from collections WHERE front_id = $frontId""".map(_.string("id")).single.apply() }) should be (DB localTx { implicit session => - sql"""SELECT id from cards WHERE collection_id = $collectionId""".map(_.string("id")).list().apply() + sql"""SELECT id from cards WHERE collection_id = $collectionId""".map(_.string("id")).list.apply() }).length shouldBe 0 } From fe089005cf7afa9aeff131bad2a2ec74dbd0b530 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:19:21 +0100 Subject: [PATCH 04/20] Bump FAPI client to version with Play 3.0 release --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c863c7b9766..66fb7356ed3 100644 --- a/build.sbt +++ b/build.sbt @@ -75,7 +75,7 @@ libraryDependencies ++= Seq( "com.gu" %% "content-api-client-aws" % "0.6", "com.gu" %% "content-api-client-default" % capiClientVersion, "com.gu" %% "editorial-permissions-client" % "2.9", - "com.gu" %% "fapi-client-play28" % "4.0.5", + "com.gu" %% "fapi-client-play30" % "6.0.0", "com.gu" %% "mobile-notifications-api-models" % "1.0.16", "com.gu" %% "pan-domain-auth-play_2-8" % "1.2.2", From 2aae9266622554ad201f4cf1ccf8f1bbcbee8150 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:19:39 +0100 Subject: [PATCH 05/20] Bump CAPI versions to match FAPI client --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 66fb7356ed3..50210252f2c 100644 --- a/build.sbt +++ b/build.sbt @@ -44,8 +44,8 @@ TwirlKeys.templateImports ++= Seq( routesImport += "model.editions._" val awsVersion = "1.12.470" -val capiModelsVersion = "17.5.1" -val capiClientVersion = "19.2.1" +val capiModelsVersion = "23.0.0" +val capiClientVersion = "26.0.0" val json4sVersion = "4.0.3" val enumeratumPlayVersion = "1.6.0" val circeVersion = "0.13.0" From 6f3b7e02fd1c582e4931aff270f9f64df8e2c900 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:19:52 +0100 Subject: [PATCH 06/20] Bump panda client to version which supports Play 3.0 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 50210252f2c..ae427b9267b 100644 --- a/build.sbt +++ b/build.sbt @@ -77,7 +77,7 @@ libraryDependencies ++= Seq( "com.gu" %% "editorial-permissions-client" % "2.9", "com.gu" %% "fapi-client-play30" % "6.0.0", "com.gu" %% "mobile-notifications-api-models" % "1.0.16", - "com.gu" %% "pan-domain-auth-play_2-8" % "1.2.2", + "com.gu" %% "pan-domain-auth-play_3-0" % "3.0.1", "org.scanamo" %% "scanamo" % "1.0.0-M15" exclude("org.scala-lang.modules", "scala-java8-compat_2.13"), "com.github.blemale" %% "scaffeine" % "4.1.0" % "compile", From ee171abe22044ee5d3ac09ba700f7d1a5c3b6d4e Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:20:13 +0100 Subject: [PATCH 07/20] Bump Play to 3.0.2 --- build.sbt | 4 ++-- project/plugins.sbt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index ae427b9267b..366cbf473df 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ libraryDependencies ++= Seq( "org.julienrf" %% "play-json-derived-codecs" % "5.0.0", "org.json4s" %% "json4s-native" % json4sVersion, "org.json4s" %% "json4s-jackson" % json4sVersion, - "com.typesafe.play" %% "play-json-joda" % "2.9.2", + "org.playframework" %% "play-json-joda" % "3.0.2", "ai.x" %% "play-json-extensions" % "0.40.2", "org.postgresql" % "postgresql" % "42.3.9", @@ -101,7 +101,7 @@ libraryDependencies ++= Seq( "com.beachape" %% "enumeratum" % enumeratumPlayVersion, "com.beachape" %% "enumeratum-play" % enumeratumPlayVersion, - "com.typesafe.play" %% "play" % "2.8.2", + "org.playframework" %% "play" % "3.0.2", "org.apache.commons" % "commons-text" % "1.10.0", "com.beust" % "jcommander" % "1.75", diff --git a/project/plugins.sbt b/project/plugins.sbt index ff7bfa72582..bac170871bf 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -12,7 +12,7 @@ resolvers ++= Seq( "Spy" at "https://files.couchbase.com/maven2/" ) -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.11") +addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.2") addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.3") From 339bb242697b6a37a9bb4e31bbb5440099dba19e Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:20:48 +0100 Subject: [PATCH 08/20] Bump SBT to 1.9.6 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 563a014da4a..27430827bc2 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.7.2 +sbt.version=1.9.6 From e6ffba6848de48ecff9b2bb6a9d2d6341de8e615 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:21:04 +0100 Subject: [PATCH 09/20] Bump to latest patch Scala version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 366cbf473df..00d50c448b2 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ packageSummary := "Facia tool" packageDescription := "Guardian front pages editor" -ThisBuild / scalaVersion := "2.13.5" +ThisBuild / scalaVersion := "2.13.13" import sbt.Resolver From e6af066eaec9244c6490e177c1576ae4aea5dbb5 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 9 Apr 2024 17:21:13 +0100 Subject: [PATCH 10/20] Resolve dependency conflicts --- build.sbt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.sbt b/build.sbt index 00d50c448b2..04b4c569d80 100644 --- a/build.sbt +++ b/build.sbt @@ -110,6 +110,17 @@ libraryDependencies ++= Seq( "org.mockito" % "mockito-core" % "5.11.0" % Test ) +dependencyOverrides ++= Seq( + // Pinned to resolve transitive dependencies between Play and Scalikejdbc + "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.1", +) + +// Until all dependencies are on scala-java8-compat v1.x, this avoids unnecessary fatal eviction errors +libraryDependencySchemes ++= Seq( + "org.scala-lang.modules" %% "scala-java8-compat" % VersionScheme.Always, + "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always +) + val UsesDatabaseTest = config("database-int") extend Test lazy val root = (project in file(".")) From 95601f86898657c956510d14c7d76cf72b085cc2 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 7 May 2024 12:42:15 +0100 Subject: [PATCH 11/20] Add missing type annotations for implicits --- app/controllers/CollectionController.scala | 6 +++--- app/controllers/DefaultsController.scala | 4 ++-- app/controllers/FaciaContentApiProxy.scala | 5 ++--- app/controllers/FaciaToolV2Controller.scala | 4 ++-- app/controllers/PressController.scala | 4 ++-- app/controllers/StoriesVisibleController.scala | 4 ++-- app/logging/Logging.scala | 2 +- app/model/FeatureSwitches.scala | 4 ++-- app/model/UserData.scala | 6 +++--- app/model/editions/EditionsAppTemplates.scala | 10 +++++----- app/model/editions/EditionsCard.scala | 10 +++++----- .../editions/EditionsClientCollection.scala | 8 ++++---- app/model/editions/EditionsCollection.scala | 5 ++--- app/model/editions/EditionsFront.scala | 6 +++--- app/model/editions/IssueVersion.scala | 8 +++----- .../editions/client/ClientCardMetadata.scala | 3 ++- app/model/forms/CreateIssue.scala | 5 ++--- app/model/forms/GetCollectionsFilter.scala | 4 ++-- app/model/frontsapi.scala | 2 +- app/services/AssetsManager.scala | 4 ++-- app/services/CollectionService.scala | 6 +++--- app/services/ContainerService.scala | 4 ++-- app/services/Ophan.scala | 9 ++++----- app/services/editions/prefills/package.scala | 5 ++--- .../publishing/PublishedIssueFormatters.scala | 16 ++++++++-------- app/slices/ContainerJsonConfig.scala | 4 ++-- app/slices/Story.scala | 6 +++--- app/updates/ClientHydratedCollection.scala | 6 +++--- app/updates/UpdateMessage.scala | 4 ++-- app/util/Acl.scala | 6 +++--- 30 files changed, 82 insertions(+), 88 deletions(-) diff --git a/app/controllers/CollectionController.scala b/app/controllers/CollectionController.scala index ef3fe4491e5..ee61a09eee2 100644 --- a/app/controllers/CollectionController.scala +++ b/app/controllers/CollectionController.scala @@ -4,7 +4,7 @@ import scala.concurrent.ExecutionContext import com.gu.facia.client.models.CollectionConfigJson import config.UpdateManager import permissions.ConfigPermissionCheck -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import services.Press import updates._ import util.Acl @@ -12,7 +12,7 @@ import util.Requests._ import logging.Logging object CollectionRequest { - implicit val jsonFormat = Json.format[CollectionRequest] + implicit val jsonFormat: OFormat[CollectionRequest] = Json.format[CollectionRequest] } case class CollectionRequest( @@ -21,7 +21,7 @@ case class CollectionRequest( ) object CreateCollectionResponse { - implicit val jsonFormat = Json.format[CreateCollectionResponse] + implicit val jsonFormat: OFormat[CreateCollectionResponse] = Json.format[CreateCollectionResponse] } case class CreateCollectionResponse(id: String) diff --git a/app/controllers/DefaultsController.scala b/app/controllers/DefaultsController.scala index 22f06dfca60..7b629b1d918 100644 --- a/app/controllers/DefaultsController.scala +++ b/app/controllers/DefaultsController.scala @@ -5,12 +5,12 @@ import model.editions.{EditionsAppTemplates, FeastAppTemplates} import model.editions.templates.CuratedPlatformDefinition import model.{Cached, UserDataForDefaults} import permissions.Permissions -import play.api.libs.json.{JsValue, Json} +import play.api.libs.json.{JsValue, Json, OWrites} import switchboard.SwitchManager import util.{Acl, AclJson} object Defaults { - implicit val jsonFormat = Json.writes[Defaults] + implicit val jsonFormat: OWrites[Defaults] = Json.writes[Defaults] } case class Defaults( diff --git a/app/controllers/FaciaContentApiProxy.scala b/app/controllers/FaciaContentApiProxy.scala index 6e8bcdd0255..4a4faa7059b 100644 --- a/app/controllers/FaciaContentApiProxy.scala +++ b/app/controllers/FaciaContentApiProxy.scala @@ -1,11 +1,10 @@ package controllers import java.net.{URI, URLEncoder} - import com.gu.contentapi.client.IAMEncoder import metrics.FaciaToolMetrics import model.Cached -import play.api.libs.concurrent.Futures +import play.api.libs.concurrent.{DefaultFutures, Futures} import play.api.libs.concurrent.Futures._ import scala.concurrent.duration._ @@ -18,7 +17,7 @@ import scala.concurrent.ExecutionContext class FaciaContentApiProxy(capi: Capi, val deps: BaseFaciaControllerComponents)(implicit ec: ExecutionContext) extends BaseFaciaController(deps) with Logging { - implicit val futures = new play.api.libs.concurrent.DefaultFutures(org.apache.pekko.actor.ActorSystem()) + implicit val futures: DefaultFutures = new play.api.libs.concurrent.DefaultFutures(org.apache.pekko.actor.ActorSystem()) implicit class string2encodings(s: String) { lazy val urlEncoded = URLEncoder.encode(s, "utf-8") } diff --git a/app/controllers/FaciaToolV2Controller.scala b/app/controllers/FaciaToolV2Controller.scala index d46a6b1f709..b2ddb56370b 100644 --- a/app/controllers/FaciaToolV2Controller.scala +++ b/app/controllers/FaciaToolV2Controller.scala @@ -4,7 +4,7 @@ import frontsapi.model.UpdateActions import logging.Logging import metrics.FaciaToolMetrics import model.NoCache -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import services._ import updates._ import util.Acl @@ -16,7 +16,7 @@ import permissions.CollectionPermissions import scala.concurrent.{ExecutionContext, Future} object CollectionSpec { - implicit val jsonFormat = Json.format[CollectionSpec] + implicit val jsonFormat: OFormat[CollectionSpec] = Json.format[CollectionSpec] } case class CollectionSpec(id: String, lastUpdated: Option[Long]) diff --git a/app/controllers/PressController.scala b/app/controllers/PressController.scala index 78f32c7c2d2..ce30233d982 100644 --- a/app/controllers/PressController.scala +++ b/app/controllers/PressController.scala @@ -3,11 +3,11 @@ package controllers import com.amazonaws.services.dynamodbv2.AmazonDynamoDB import org.scanamo.generic.auto.genericDerivedFormat import org.scanamo.{Scanamo, Table} -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import software.amazon.awssdk.services.dynamodb.DynamoDbClient object FrontPressRecord { - implicit val jsonFormat = Json.format[FrontPressRecord] + implicit val jsonFormat: OFormat[FrontPressRecord] = Json.format[FrontPressRecord] } case class FrontPressRecord ( stageName: String, diff --git a/app/controllers/StoriesVisibleController.scala b/app/controllers/StoriesVisibleController.scala index 89545b414c2..eaf7af0df24 100644 --- a/app/controllers/StoriesVisibleController.scala +++ b/app/controllers/StoriesVisibleController.scala @@ -1,12 +1,12 @@ package controllers import logging.Logging -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import services.ContainerService import slices.Story object StoriesVisibleRequest { - implicit val jsonFormat = Json.format[StoriesVisibleRequest] + implicit val jsonFormat: OFormat[StoriesVisibleRequest] = Json.format[StoriesVisibleRequest] } case class StoriesVisibleRequest( diff --git a/app/logging/Logging.scala b/app/logging/Logging.scala index a17fa7fb50b..b72e44d8da6 100644 --- a/app/logging/Logging.scala +++ b/app/logging/Logging.scala @@ -3,5 +3,5 @@ package logging import play.api.Logger trait Logging { - implicit val logger = Logger(getClass) + implicit val logger: Logger = Logger(getClass) } diff --git a/app/model/FeatureSwitches.scala b/app/model/FeatureSwitches.scala index 4562a337a09..0383ee28ca6 100644 --- a/app/model/FeatureSwitches.scala +++ b/app/model/FeatureSwitches.scala @@ -1,9 +1,9 @@ package model -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} object FeatureSwitch { - implicit val jsonFormat = Json.format[FeatureSwitch] + implicit val jsonFormat: OFormat[FeatureSwitch] = Json.format[FeatureSwitch] } case class FeatureSwitch( diff --git a/app/model/UserData.scala b/app/model/UserData.scala index 726054f225f..580c94b5ad9 100644 --- a/app/model/UserData.scala +++ b/app/model/UserData.scala @@ -2,12 +2,12 @@ package model import com.gu.facia.client.models.Trail import org.scanamo.{DynamoFormat, TypeCoercionError} -import play.api.libs.json.{JsValue, Json} +import play.api.libs.json.{JsValue, Json, OFormat} import scala.util.{Failure, Success, Try} object UserData { - implicit val jsonFormat = Json.format[UserData] + implicit val jsonFormat: OFormat[UserData] = Json.format[UserData] implicit val jsValueFormat: DynamoFormat[JsValue] = DynamoFormat.xmap[JsValue, String]( x => Try(Json.parse(x)) match { @@ -39,7 +39,7 @@ case class UserData( ) object UserDataForDefaults { - implicit val jsonFormat = Json.format[UserDataForDefaults] + implicit val jsonFormat: OFormat[UserDataForDefaults] = Json.format[UserDataForDefaults] def fromUserData(userData: UserData, clipboardArticles: Option[List[Trail]]): UserDataForDefaults = { val featureSwitches = userData.featureSwitches.fold(FeatureSwitches.all) { userFeatureSwitches => diff --git a/app/model/editions/EditionsAppTemplates.scala b/app/model/editions/EditionsAppTemplates.scala index abf76b8b7f0..f4ad3c84579 100644 --- a/app/model/editions/EditionsAppTemplates.scala +++ b/app/model/editions/EditionsAppTemplates.scala @@ -9,7 +9,7 @@ import model.editions.templates.TemplateHelpers.Defaults import model.editions.templates._ import model.editions.templates.feast.{FeastNorthernHemisphere, FeastSouthernHemisphere} import org.postgresql.util.PGobject -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import services.editions.prefills.CapiQueryTimeWindow @@ -70,7 +70,7 @@ object CuratedPlatform extends PlayEnum[CuratedPlatform] { } case object WeekDay extends Enumeration(1) { - implicit lazy val implicitConversions = scala.language.implicitConversions + implicit lazy val implicitConversions: languageFeature.implicitConversions = scala.language.implicitConversions type WeekDay = Value val Mon, Tues, Wed, Thurs, Fri, Sat, Sun = Value @@ -133,11 +133,11 @@ object Edition extends PlayEnum[Edition] { } case class FrontPresentation(swatch: Swatch) { - implicit def frontPresentationFormat = Json.format[FrontPresentation] + implicit def frontPresentationFormat: OFormat[FrontPresentation] = Json.format[FrontPresentation] } object FrontPresentation { - implicit def frontPresentationFormat = Json.format[FrontPresentation] + implicit def frontPresentationFormat: OFormat[FrontPresentation] = Json.format[FrontPresentation] } case class CollectionPresentation() @@ -152,7 +152,7 @@ case class CapiPrefillQuery(queryString: String, pathType: PathType) { } object CapiPrefillQuery { - implicit def format = Json.format[CapiPrefillQuery] + implicit def format: OFormat[CapiPrefillQuery] = Json.format[CapiPrefillQuery] } import model.editions.WeekDay._ diff --git a/app/model/editions/EditionsCard.scala b/app/model/editions/EditionsCard.scala index 42859e33a0b..c3a685d26e1 100644 --- a/app/model/editions/EditionsCard.scala +++ b/app/model/editions/EditionsCard.scala @@ -3,7 +3,7 @@ package model.editions import enumeratum.EnumEntry.Uncapitalised import enumeratum.{EnumEntry, PlayEnum} import logging.Logging -import play.api.libs.json.Json +import play.api.libs.json.{JsResult, Json, OFormat} import scalikejdbc.WrappedResultSet case class Image ( @@ -17,13 +17,13 @@ case class Image ( } object Image { - implicit val format = Json.format[Image] + implicit val format: OFormat[Image] = Json.format[Image] } case class CoverCardImages(mobile: Option[Image], tablet: Option[Image]) object CoverCardImages { - implicit val format = Json.format[CoverCardImages] + implicit val format: OFormat[CoverCardImages] = Json.format[CoverCardImages] } case class CardMetadata( @@ -47,7 +47,7 @@ case class CardMetadata( ) object CardMetadata { - implicit val format = Json.format[CardMetadata] + implicit val format: OFormat[CardMetadata] = Json.format[CardMetadata] val default = CardMetadata(None, None, None, None, None, None, None, None, None, None, None, None, None) } @@ -109,7 +109,7 @@ case class EditionsCard(id: String, cardType: CardType, addedOn: Long, metadata: } object EditionsCard extends Logging { - implicit val writes = Json.format[EditionsCard] + implicit val writes: OFormat[EditionsCard] = Json.format[EditionsCard] def fromRowOpt(rs: WrappedResultSet, prefix: String = ""): Option[EditionsCard] = { for { diff --git a/app/model/editions/EditionsClientCollection.scala b/app/model/editions/EditionsClientCollection.scala index 1215b767772..19ca9ee5cf6 100644 --- a/app/model/editions/EditionsClientCollection.scala +++ b/app/model/editions/EditionsClientCollection.scala @@ -1,7 +1,7 @@ package model.editions import model.editions.client.ClientCardMetadata -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import services.editions.prefills.CapiQueryTimeWindow // Ideally the frontend can be changed so we don't have this weird modelling! @@ -41,9 +41,9 @@ case class EditionsClientCollection( case class EditionsFrontendCollectionWrapper(id: String, collection: EditionsClientCollection) object EditionsFrontendCollectionWrapper { - implicit def cardFormat = Json.format[EditionsClientCard] - implicit def collectionFormat = Json.format[EditionsClientCollection] - implicit def collectionWrapperFormat = Json.format[EditionsFrontendCollectionWrapper] + implicit def cardFormat: OFormat[EditionsClientCard] = Json.format[EditionsClientCard] + implicit def collectionFormat: OFormat[EditionsClientCollection] = Json.format[EditionsClientCollection] + implicit def collectionWrapperFormat: OFormat[EditionsFrontendCollectionWrapper] = Json.format[EditionsFrontendCollectionWrapper] def fromCollection(collection: EditionsCollection): EditionsFrontendCollectionWrapper = { EditionsFrontendCollectionWrapper( diff --git a/app/model/editions/EditionsCollection.scala b/app/model/editions/EditionsCollection.scala index de69f71014c..333aed97972 100644 --- a/app/model/editions/EditionsCollection.scala +++ b/app/model/editions/EditionsCollection.scala @@ -1,8 +1,7 @@ package model.editions import java.time.ZonedDateTime - -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import scalikejdbc.WrappedResultSet import services.editions.prefills.CapiQueryTimeWindow @@ -25,7 +24,7 @@ case class EditionsCollection( } object EditionsCollection { - implicit val format = Json.format[EditionsCollection] + implicit val format: OFormat[EditionsCollection] = Json.format[EditionsCollection] def fromRow(rs: WrappedResultSet, prefix: String = ""): EditionsCollection = { val capiPrefillQuery: Option[CapiPrefillQuery] = diff --git a/app/model/editions/EditionsFront.scala b/app/model/editions/EditionsFront.scala index d02c5f98b8c..b38c26dee49 100644 --- a/app/model/editions/EditionsFront.scala +++ b/app/model/editions/EditionsFront.scala @@ -1,11 +1,11 @@ package model.editions import org.postgresql.util.PGobject -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat, OWrites} import scalikejdbc.WrappedResultSet object EditionsFrontMetadata { - implicit val format = Json.format[EditionsFrontMetadata] + implicit val format: OFormat[EditionsFrontMetadata] = Json.format[EditionsFrontMetadata] } case class EditionsFrontMetadata(nameOverride: Option[String], swatch: Option[Swatch]) { @@ -45,7 +45,7 @@ case class EditionsFront( } object EditionsFront { - implicit val writes = Json.writes[EditionsFront] + implicit val writes: OWrites[EditionsFront] = Json.writes[EditionsFront] def fromRow(rs: WrappedResultSet, prefix: String = ""): EditionsFront = { EditionsFront( diff --git a/app/model/editions/IssueVersion.scala b/app/model/editions/IssueVersion.scala index 20eafd20f58..ce6cdb83226 100644 --- a/app/model/editions/IssueVersion.scala +++ b/app/model/editions/IssueVersion.scala @@ -1,6 +1,6 @@ package model.editions -import play.api.libs.json.Json +import play.api.libs.json.{Format, Json, OFormat} import scalikejdbc.WrappedResultSet import enumeratum.{EnumEntry, PlayEnum} @@ -28,8 +28,7 @@ case class IssueVersionEvent( ) object IssueVersionEvent { - implicit val reads = Json.reads[IssueVersionEvent] - implicit val writes = Json.writes[IssueVersionEvent] + implicit val format: Format[IssueVersionEvent] = Json.format[IssueVersionEvent] def fromRow(rs: WrappedResultSet): IssueVersionEvent = IssueVersionEvent( rs.zonedDateTime("event_time").toInstant.toEpochMilli, @@ -47,8 +46,7 @@ case class IssueVersion( ) object IssueVersion { - implicit val reads = Json.reads[IssueVersion] - implicit val writes = Json.writes[IssueVersion] + implicit val format: OFormat[IssueVersion] = Json.format[IssueVersion] def fromRow(rs: WrappedResultSet): IssueVersion = IssueVersion( rs.string("version_id"), diff --git a/app/model/editions/client/ClientCardMetadata.scala b/app/model/editions/client/ClientCardMetadata.scala index ce50b27a1c7..ce96206f2ff 100644 --- a/app/model/editions/client/ClientCardMetadata.scala +++ b/app/model/editions/client/ClientCardMetadata.scala @@ -2,6 +2,7 @@ package model.editions.client import ai.x.play.json.Jsonx import model.editions.{CardMetadata, CoverCardImages, Image, MediaType} +import play.api.libs.json.OFormat // This is a subset of the shared model here - https://github.com/guardian/facia-scala-client/blob/master/facia-json/src/main/scala/com/gu/facia/client/models/Collection.scala#L18 // Why not reuse that model? We only want to surface the fields necessary for editions @@ -82,7 +83,7 @@ case class ClientCardMetadata( } object ClientCardMetadata { - implicit val format = Jsonx.formatCaseClassUseDefaults[ClientCardMetadata] + implicit val format: OFormat[ClientCardMetadata] = Jsonx.formatCaseClassUseDefaults[ClientCardMetadata] def fromCardMetadata(cardMetadata: CardMetadata): ClientCardMetadata = { val mediaType: MediaType = cardMetadata.mediaType.getOrElse(MediaType.UseArticleTrail) diff --git a/app/model/forms/CreateIssue.scala b/app/model/forms/CreateIssue.scala index 64b18a0b359..88b8626c00d 100644 --- a/app/model/forms/CreateIssue.scala +++ b/app/model/forms/CreateIssue.scala @@ -1,12 +1,11 @@ package model.forms import java.time.LocalDate - -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} case class CreateIssue(issueDate: LocalDate) object CreateIssue { - implicit val format = Json.format[CreateIssue] + implicit val format: OFormat[CreateIssue] = Json.format[CreateIssue] } diff --git a/app/model/forms/GetCollectionsFilter.scala b/app/model/forms/GetCollectionsFilter.scala index de841485267..42ccbdd3040 100644 --- a/app/model/forms/GetCollectionsFilter.scala +++ b/app/model/forms/GetCollectionsFilter.scala @@ -1,10 +1,10 @@ package model.forms -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} case class GetCollectionsFilter(id: String, lastUpdated: Option[Long]) object GetCollectionsFilter { - implicit val format = Json.format[GetCollectionsFilter] + implicit val format: OFormat[GetCollectionsFilter] = Json.format[GetCollectionsFilter] } diff --git a/app/model/frontsapi.scala b/app/model/frontsapi.scala index ae3032fc9b7..21330b66cee 100644 --- a/app/model/frontsapi.scala +++ b/app/model/frontsapi.scala @@ -59,7 +59,7 @@ trait UpdateActionsTrait extends Logging { def config: ApplicationConfiguration def configAgent: ConfigAgent def structuredLogger: StructuredLogger - implicit val updateListWrite = Json.writes[UpdateList] + implicit val updateListWrite: OWrites[UpdateList] = Json.writes[UpdateList] def insertIntoLive(update: UpdateList, identity: User, collectionJson: CollectionJson): CollectionJson = if (update.live) { diff --git a/app/services/AssetsManager.scala b/app/services/AssetsManager.scala index 40b61f4830b..8b564aea27d 100644 --- a/app/services/AssetsManager.scala +++ b/app/services/AssetsManager.scala @@ -3,7 +3,7 @@ package services import java.io.FileInputStream import conf.ApplicationConfiguration import play.api.libs.functional.syntax._ -import play.api.libs.json.{JsError, JsPath, JsSuccess, Json} +import play.api.libs.json.{JsError, JsPath, JsSuccess, Json, Reads} import scala.io.Source @@ -11,7 +11,7 @@ import scala.io.Source class InvalidAssetsException(msg: String) extends RuntimeException(msg) object Bundles { - implicit val jsonRead = ( + implicit val jsonRead: Reads[Bundles] = ( (JsPath \ "config.js").read[String] and (JsPath \ "collections.js").read[String] )(Bundles.apply _) diff --git a/app/services/CollectionService.scala b/app/services/CollectionService.scala index 934d8e20da3..4628a0efe35 100644 --- a/app/services/CollectionService.scala +++ b/app/services/CollectionService.scala @@ -2,7 +2,7 @@ package services import com.gu.facia.client.models.{CollectionJson, ConfigJson, Trail} import metrics.FaciaToolMetrics -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import slices.Story import scala.concurrent.{ExecutionContext, Future} @@ -10,7 +10,7 @@ import scala.concurrent.{ExecutionContext, Future} case class StoriesVisibleByStage(live: Option[StoriesVisibleResponse], draft: Option[StoriesVisibleResponse]) object StoriesVisibleByStage { - implicit val jsonFormat = Json.format[StoriesVisibleByStage] + implicit val jsonFormat: OFormat[StoriesVisibleByStage] = Json.format[StoriesVisibleByStage] } case class CollectionAndStoriesResponse(id: String, collection: CollectionJson, storiesVisibleByStage: Option[StoriesVisibleByStage]) { @@ -21,7 +21,7 @@ case class CollectionAndStoriesResponse(id: String, collection: CollectionJson, } object CollectionAndStoriesResponse { - implicit val jsonFormat = Json.format[CollectionAndStoriesResponse] + implicit val jsonFormat: OFormat[CollectionAndStoriesResponse] = Json.format[CollectionAndStoriesResponse] } class CollectionService(frontsApi: FrontsApi, containerService: ContainerService)(implicit ec: ExecutionContext) { diff --git a/app/services/ContainerService.scala b/app/services/ContainerService.scala index 720eb626063..df8e3dbd8ca 100644 --- a/app/services/ContainerService.scala +++ b/app/services/ContainerService.scala @@ -1,6 +1,6 @@ package services -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import slices._ case class StoriesVisibleResponse( @@ -9,7 +9,7 @@ case class StoriesVisibleResponse( ) object StoriesVisibleResponse { - implicit val jsonFormat = Json.format[StoriesVisibleResponse] + implicit val jsonFormat: OFormat[StoriesVisibleResponse] = Json.format[StoriesVisibleResponse] } class ContainerService(val containers: Containers) { diff --git a/app/services/Ophan.scala b/app/services/Ophan.scala index f58d7af0084..f48e5a6232c 100644 --- a/app/services/Ophan.scala +++ b/app/services/Ophan.scala @@ -2,17 +2,16 @@ package services import java.io.IOException import java.time.LocalDate - import conf.ApplicationConfiguration import logging.Logging -import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeUnit import com.github.blemale.scaffeine.{Cache, Scaffeine} import com.gu.contentapi.client.model.HttpResponse -import model.editions.{OphanQueryPrefillParams} +import model.editions.OphanQueryPrefillParams import okhttp3.{Call, Callback, ConnectionPool, OkHttpClient, Response} import okhttp3.Request.Builder -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import scala.concurrent.duration._ import scala.concurrent.{ExecutionContext, Future, Promise} @@ -23,7 +22,7 @@ class GuardianOphan(config: ApplicationConfiguration)(implicit ex: ExecutionCont val DEFAULT_OPHAN_ADDRESS = "https://api.ophan.co.uk/api" val promotionPath = "/promotion/front/" - implicit val ophanScoreReads = Json.format[OphanScore] + implicit val ophanScoreReads: OFormat[OphanScore] = Json.format[OphanScore] def getOphanScores(maybePath: Option[String], baseDate: LocalDate, maybeOphanQueryPrefillParams: Option[OphanQueryPrefillParams]): Future[Option[Array[OphanScore]]] = { val maybeDates = maybeOphanQueryPrefillParams.map(ophanQueryPrefillParams => ( diff --git a/app/services/editions/prefills/package.scala b/app/services/editions/prefills/package.scala index 59369deb3ab..0d85ba6d842 100644 --- a/app/services/editions/prefills/package.scala +++ b/app/services/editions/prefills/package.scala @@ -1,10 +1,9 @@ package services.editions import java.time.{Instant, LocalDate} - import com.gu.facia.api.utils.ResolvedMetaData import model.editions._ -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} package object prefills { @@ -24,7 +23,7 @@ package object prefills { case class CapiQueryTimeWindow(fromDate: Instant, toDate: Instant) object CapiQueryTimeWindow { - implicit def format = Json.format[CapiQueryTimeWindow] + implicit def format: OFormat[CapiQueryTimeWindow] = Json.format[CapiQueryTimeWindow] } case class MetadataForLogging(issueDate: LocalDate, collectionId: Option[String], collectionName: Option[String]) { diff --git a/app/services/editions/publishing/PublishedIssueFormatters.scala b/app/services/editions/publishing/PublishedIssueFormatters.scala index 4448b71d4d0..a7306505208 100644 --- a/app/services/editions/publishing/PublishedIssueFormatters.scala +++ b/app/services/editions/publishing/PublishedIssueFormatters.scala @@ -1,14 +1,14 @@ package services.editions.publishing import model.editions._ -import play.api.libs.json.Json +import play.api.libs.json.{Json, OWrites} object PublishedIssueFormatters { - implicit val publishedImageWrites = Json.writes[PublishedImage] - implicit val publishedCardImageWrites = Json.writes[PublishedCardImage] - implicit val publishedFurnitureWrites = Json.writes[PublishedFurniture] - implicit val publishedArticleWrites = Json.writes[PublishedArticle] - implicit val publishedCollectionsWrites = Json.writes[PublishedCollection] - implicit val publishedFrontsWrites = Json.writes[PublishedFront] - implicit val publishedIssueWrites = Json.writes[PublishableIssue] + implicit val publishedImageWrites: OWrites[PublishedImage] = Json.writes[PublishedImage] + implicit val publishedCardImageWrites: OWrites[PublishedCardImage] = Json.writes[PublishedCardImage] + implicit val publishedFurnitureWrites: OWrites[PublishedFurniture] = Json.writes[PublishedFurniture] + implicit val publishedArticleWrites: OWrites[PublishedArticle] = Json.writes[PublishedArticle] + implicit val publishedCollectionsWrites: OWrites[PublishedCollection] = Json.writes[PublishedCollection] + implicit val publishedFrontsWrites: OWrites[PublishedFront] = Json.writes[PublishedFront] + implicit val publishedIssueWrites: OWrites[PublishableIssue] = Json.writes[PublishableIssue] } diff --git a/app/slices/ContainerJsonConfig.scala b/app/slices/ContainerJsonConfig.scala index 326beee2f2c..2a038ac80db 100644 --- a/app/slices/ContainerJsonConfig.scala +++ b/app/slices/ContainerJsonConfig.scala @@ -1,9 +1,9 @@ package slices -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} object ContainerJsonConfig { - implicit val jsonFormat = Json.format[ContainerJsonConfig] + implicit val jsonFormat: OFormat[ContainerJsonConfig] = Json.format[ContainerJsonConfig] } case class ContainerJsonConfig( diff --git a/app/slices/Story.scala b/app/slices/Story.scala index 9ce51b915b2..e0b8046d55e 100644 --- a/app/slices/Story.scala +++ b/app/slices/Story.scala @@ -1,12 +1,12 @@ package slices -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} import util.Maps._ object Story { - implicit val jsonFormat = Json.format[Story] + implicit val jsonFormat: OFormat[Story] = Json.format[Story] - implicit val ordering = Ordering.by[Story, Int](_.group) + implicit val ordering: Ordering[Story] = Ordering.by[Story, Int](_.group) def unboosted(n: Int) = Story(n, isBoosted = false) diff --git a/app/updates/ClientHydratedCollection.scala b/app/updates/ClientHydratedCollection.scala index 2794c58fd3e..c5889945527 100644 --- a/app/updates/ClientHydratedCollection.scala +++ b/app/updates/ClientHydratedCollection.scala @@ -1,6 +1,6 @@ package updates -import play.api.libs.json.Json +import play.api.libs.json.{Json, OFormat} case class ClientHydratedTrail ( topic: Option[String], @@ -16,12 +16,12 @@ case class ClientHydratedTrail ( blockId: Option[String] ) {} object ClientHydratedTrail { - implicit val jsonFormat = Json.format[ClientHydratedTrail] + implicit val jsonFormat: OFormat[ClientHydratedTrail] = Json.format[ClientHydratedTrail] } case class ClientHydratedCollection ( trails: List[ClientHydratedTrail] ) {} object ClientHydratedCollection { - implicit val jsonFormat = Json.format[ClientHydratedCollection] + implicit val jsonFormat: OFormat[ClientHydratedCollection] = Json.format[ClientHydratedCollection] } diff --git a/app/updates/UpdateMessage.scala b/app/updates/UpdateMessage.scala index c9bfbeec03a..64c6affc3b7 100644 --- a/app/updates/UpdateMessage.scala +++ b/app/updates/UpdateMessage.scala @@ -12,7 +12,7 @@ sealed trait UpdateMessage { /* Config updates */ object CreateFront { - implicit val jsonFormat = Json.format[CreateFront].filter(_.id.matches("""^[a-z0-9\/\-+]*$""")) + implicit val jsonFormat: Reads[CreateFront] = Json.format[CreateFront].filter(_.id.matches("""^[a-z0-9\/\-+]*$""")) } case class CreateFront( id: String, @@ -101,7 +101,7 @@ case class V2CollectionUpdate(id: String, collection: CollectionJson) extends Up /* Macro - Watch out, this needs to be after the case classes */ object UpdateMessage { - implicit val format = derived.flat.oformat[UpdateMessage]((__ \ "type").format[String]) + implicit val format: OFormat[UpdateMessage] = derived.flat.oformat[UpdateMessage]((__ \ "type").format[String]) } /* Kinesis messages */ diff --git a/app/util/Acl.scala b/app/util/Acl.scala index 90b4652fd23..558a680fcbc 100644 --- a/app/util/Acl.scala +++ b/app/util/Acl.scala @@ -3,11 +3,11 @@ package util import com.gu.permissions.{PermissionDefinition, PermissionsProvider} import logging.Logging import permissions._ -import play.api.libs.json.{JsBoolean, JsValue, Json, Writes} +import play.api.libs.json.{JsBoolean, JsValue, Json, OWrites, Writes} import switchboard.SwitchManager object Authorization { - implicit val authorizationWrites = new Writes[Authorization] { + implicit val authorizationWrites: Writes[Authorization] = new Writes[Authorization] { def writes(access: Authorization): JsValue = access match { case AccessGranted => JsBoolean(true) case AccessDenied => JsBoolean(false)}} @@ -18,7 +18,7 @@ object AccessGranted extends Authorization object AccessDenied extends Authorization object AclJson { - implicit val jsonWrites = Json.writes[AclJson] + implicit val jsonWrites: OWrites[AclJson] = Json.writes[AclJson] } case class AclJson ( From 2b15b6625978a5bc162d034552098f745ec67651 Mon Sep 17 00:00:00 2001 From: David Furey Date: Wed, 10 Apr 2024 08:43:44 +0100 Subject: [PATCH 12/20] Assets without environment is deprecated --- app/Components.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Components.scala b/app/Components.scala index 968f4797ea9..95e8f3310ce 100644 --- a/app/Components.scala +++ b/app/Components.scala @@ -117,7 +117,7 @@ class AppComponents(context: Context, val config: ApplicationConfiguration) allowedOrigins = Origins.Matching(Set(config.environment.applicationUrl)) ) - override lazy val assets: Assets = new controllers.Assets(httpErrorHandler, assetsMetadata) + override lazy val assets: Assets = new controllers.Assets(httpErrorHandler, assetsMetadata, environment) val router: Router = new Routes(httpErrorHandler, status, pandaAuth, v2Assets, v1Assets, views, faciaTool, pressController, faciaToolV2, defaults, userDataController, faciaCapiProxy, thumbnail, front, collection, storiesVisible, vanityRedirects, troubleshoot, v2App, gridProxy, editions) From 7ea3b163391c2a1cdd4a424687e171b605ce9822 Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 7 May 2024 12:42:55 +0100 Subject: [PATCH 13/20] Target is deprecated --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 04b4c569d80..88c554fd6a5 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,7 @@ Universal / javaOptions ++= Seq( routesGenerator := InjectedRoutesGenerator -scalacOptions := Seq("-unchecked", "-deprecation", "-target:jvm-11", "-Xcheckinit", "-encoding", "utf8", "-feature") +scalacOptions := Seq("-unchecked", "-deprecation", "-release:11", "-Xcheckinit", "-encoding", "utf8", "-feature") Compile / doc / sources := Seq.empty From 29e8041a29a12cb5fb646492b1022a0e4040f8de Mon Sep 17 00:00:00 2001 From: David Furey Date: Wed, 10 Apr 2024 09:56:50 +0100 Subject: [PATCH 14/20] Work around some dependency issues Caused by play-json groupId changing from com.typesafe.play to org.playframework --- build.sbt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/build.sbt b/build.sbt index 88c554fd6a5..59adce1067a 100644 --- a/build.sbt +++ b/build.sbt @@ -47,7 +47,6 @@ val awsVersion = "1.12.470" val capiModelsVersion = "23.0.0" val capiClientVersion = "26.0.0" val json4sVersion = "4.0.3" -val enumeratumPlayVersion = "1.6.0" val circeVersion = "0.13.0" resolvers ++= Seq( @@ -74,9 +73,9 @@ libraryDependencies ++= Seq( "com.gu" %% "content-api-models-json" % capiModelsVersion, "com.gu" %% "content-api-client-aws" % "0.6", "com.gu" %% "content-api-client-default" % capiClientVersion, - "com.gu" %% "editorial-permissions-client" % "2.9", + "com.gu" %% "editorial-permissions-client" % "2.15", "com.gu" %% "fapi-client-play30" % "6.0.0", - "com.gu" %% "mobile-notifications-api-models" % "1.0.16", + "com.gu" %% "mobile-notifications-api-models" % "1.0.16", // todo: waiting for mobile team to bump to Play 3.0 "com.gu" %% "pan-domain-auth-play_3-0" % "3.0.1", "org.scanamo" %% "scanamo" % "1.0.0-M15" exclude("org.scala-lang.modules", "scala-java8-compat_2.13"), @@ -84,11 +83,11 @@ libraryDependencies ++= Seq( "com.gu" %% "thrift-serializer" % "4.0.2", "net.logstash.logback" % "logstash-logback-encoder" % "6.6", - "org.julienrf" %% "play-json-derived-codecs" % "5.0.0", + "org.julienrf" %% "play-json-derived-codecs" % "5.0.0", // todo: waiting for new cut see https://github.com/julienrf/play-json-derived-codecs/pull/92 "org.json4s" %% "json4s-native" % json4sVersion, "org.json4s" %% "json4s-jackson" % json4sVersion, "org.playframework" %% "play-json-joda" % "3.0.2", - "ai.x" %% "play-json-extensions" % "0.40.2", + "ai.x" %% "play-json-extensions" % "0.40.2", // todo: more work required, see https://github.com/bizzabo/play-json-extensions/issues/94 "org.postgresql" % "postgresql" % "42.3.9", "org.scalikejdbc" %% "scalikejdbc" % "4.2.0", @@ -99,8 +98,8 @@ libraryDependencies ++= Seq( "io.circe" %% "circe-generic" % circeVersion, "io.circe" %% "circe-parser" % circeVersion, - "com.beachape" %% "enumeratum" % enumeratumPlayVersion, - "com.beachape" %% "enumeratum-play" % enumeratumPlayVersion, + "com.beachape" %% "enumeratum" % "1.7.3", + "com.beachape" %% "enumeratum-play" % "1.8.0", "org.playframework" %% "play" % "3.0.2", "org.apache.commons" % "commons-text" % "1.10.0", @@ -110,6 +109,12 @@ libraryDependencies ++= Seq( "org.mockito" % "mockito-core" % "5.11.0" % Test ) +excludeDependencies ++= Seq( + // As of Play 3.0, groupId has changed to org.playframework; exclude transitive dependencies to the old artifacts + // Hopefully this workaround can be removed once play-json-extensions either updates to Play 3.0 or is merged into play-json + ExclusionRule(organization = "com.typesafe.play") +) + dependencyOverrides ++= Seq( // Pinned to resolve transitive dependencies between Play and Scalikejdbc "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.1", From 9cca5ca7a0eb435e051973e67786cdcba3e5fe87 Mon Sep 17 00:00:00 2001 From: David Furey Date: Thu, 11 Apr 2024 13:40:47 +0100 Subject: [PATCH 15/20] Bump play-json-derived-codecs to version with Play 3.0 support --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 59adce1067a..9c9e407445d 100644 --- a/build.sbt +++ b/build.sbt @@ -83,7 +83,7 @@ libraryDependencies ++= Seq( "com.gu" %% "thrift-serializer" % "4.0.2", "net.logstash.logback" % "logstash-logback-encoder" % "6.6", - "org.julienrf" %% "play-json-derived-codecs" % "5.0.0", // todo: waiting for new cut see https://github.com/julienrf/play-json-derived-codecs/pull/92 + "org.julienrf" %% "play-json-derived-codecs" % "11.0.0", "org.json4s" %% "json4s-native" % json4sVersion, "org.json4s" %% "json4s-jackson" % json4sVersion, "org.playframework" %% "play-json-joda" % "3.0.2", From 73f91dd504cbb450b59f990c5a853637c14c3336 Mon Sep 17 00:00:00 2001 From: David Furey Date: Fri, 26 Apr 2024 17:44:37 +0100 Subject: [PATCH 16/20] Exclusion has been added, so I think this is okay as is --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9c9e407445d..c3e84602280 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ libraryDependencies ++= Seq( "org.json4s" %% "json4s-native" % json4sVersion, "org.json4s" %% "json4s-jackson" % json4sVersion, "org.playframework" %% "play-json-joda" % "3.0.2", - "ai.x" %% "play-json-extensions" % "0.40.2", // todo: more work required, see https://github.com/bizzabo/play-json-extensions/issues/94 + "ai.x" %% "play-json-extensions" % "0.40.2", "org.postgresql" % "postgresql" % "42.3.9", "org.scalikejdbc" %% "scalikejdbc" % "4.2.0", From 4280d17f3766f3b40783349227751556df6ba848 Mon Sep 17 00:00:00 2001 From: David Furey Date: Wed, 1 May 2024 17:38:52 +0100 Subject: [PATCH 17/20] Bump mobile-notifications client to version that depends on Play 3.0 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c3e84602280..75e8cc8a454 100644 --- a/build.sbt +++ b/build.sbt @@ -75,7 +75,7 @@ libraryDependencies ++= Seq( "com.gu" %% "content-api-client-default" % capiClientVersion, "com.gu" %% "editorial-permissions-client" % "2.15", "com.gu" %% "fapi-client-play30" % "6.0.0", - "com.gu" %% "mobile-notifications-api-models" % "1.0.16", // todo: waiting for mobile team to bump to Play 3.0 + "com.gu" %% "mobile-notifications-api-models" % "1.0.19", "com.gu" %% "pan-domain-auth-play_3-0" % "3.0.1", "org.scanamo" %% "scanamo" % "1.0.0-M15" exclude("org.scala-lang.modules", "scala-java8-compat_2.13"), From ed267ced3b4d5b4b656c5098219de386d15ad5bc Mon Sep 17 00:00:00 2001 From: David Furey Date: Tue, 7 May 2024 13:57:57 +0100 Subject: [PATCH 18/20] fix bad rebase --- app/services/editions/db/CollectionsQueries.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/editions/db/CollectionsQueries.scala b/app/services/editions/db/CollectionsQueries.scala index 10d2f815053..3cf6b4b6d5a 100644 --- a/app/services/editions/db/CollectionsQueries.scala +++ b/app/services/editions/db/CollectionsQueries.scala @@ -64,7 +64,7 @@ trait CollectionsQueries { val contentPrefillQueryTimeWindow = CapiQueryTimeWindow(timeWinStart, timeWinEnd) - (date, edition, zone, CapiPrefillQuery(rs.string("prefill"), pathType), contentPrefillQueryTimeWindow, rs.string("page_code")) + (date, edition, zone, CapiPrefillQuery(rs.string("prefill"), pathType), contentPrefillQueryTimeWindow, rs.string("id")) }.list.apply() rows.headOption.map { case (issueDate, edition, zone, prefillQueryUrlSegments, contentPrefillQueryTimeWindow, _) => From 126be4aa73414b84604a6f88c3400f0dc40d2daa Mon Sep 17 00:00:00 2001 From: David Furey Date: Wed, 8 May 2024 09:22:06 +0100 Subject: [PATCH 19/20] Bump Scanamo This is required because v1.0.0-M15 depends on software.amazon.awssdk:dynamodb:2.15.78 which depends on jackson-databind:2.10.5.1, which is binary incompatible with jackson-databind:2.16.2 which is depended on by com.amazonaws:aws-java-sdk-core:1.12.470. Scanamo v1.0.0 uses software.amazon.awssdk:dynamodb:2.23.4 See https://github.com/FasterXML/jackson-databind/issues/2897 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 75e8cc8a454..21c06fe72b6 100644 --- a/build.sbt +++ b/build.sbt @@ -78,7 +78,7 @@ libraryDependencies ++= Seq( "com.gu" %% "mobile-notifications-api-models" % "1.0.19", "com.gu" %% "pan-domain-auth-play_3-0" % "3.0.1", - "org.scanamo" %% "scanamo" % "1.0.0-M15" exclude("org.scala-lang.modules", "scala-java8-compat_2.13"), + "org.scanamo" %% "scanamo" % "1.1.1" exclude("org.scala-lang.modules", "scala-java8-compat_2.13"), "com.github.blemale" %% "scaffeine" % "4.1.0" % "compile", "com.gu" %% "thrift-serializer" % "4.0.2", From 7c3e961a9a575ad36ba7049e703a6d2225d06dcc Mon Sep 17 00:00:00 2001 From: David Furey Date: Wed, 8 May 2024 09:22:58 +0100 Subject: [PATCH 20/20] Re-order Dynamo format derivers to avoid warnings ``` [warn] /Users/david_furey/code/facia-tool/app/controllers/UserDataController.scala:23:69: Reference to uninitialized value Trail [warn] implicit val UserData: DynamoFormat[UserData] = deriveDynamoFormat[UserData] [warn] ^ [warn] /Users/david_furey/code/facia-tool/app/controllers/UserDataController.scala:24:63: Reference to uninitialized value JsValue [warn] implicit val Trail: DynamoFormat[Trail] = deriveDynamoFormat[Trail] [warn] ^ [warn] two warnings found ``` --- app/controllers/UserDataController.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/UserDataController.scala b/app/controllers/UserDataController.scala index b42af804da5..52e23b24719 100644 --- a/app/controllers/UserDataController.scala +++ b/app/controllers/UserDataController.scala @@ -20,16 +20,15 @@ import org.scanamo.generic.semiauto._ import scala.util.{Failure, Success, Try} class UserDataController(frontsApi: FrontsApi, dynamoClient: DynamoDbClient, val deps: BaseFaciaControllerComponents)(implicit ec: ExecutionContext) extends BaseFaciaController(deps) { - implicit val UserData: DynamoFormat[UserData] = deriveDynamoFormat[UserData] - implicit val Trail: DynamoFormat[Trail] = deriveDynamoFormat[Trail] - implicit val JsValue: DynamoFormat[JsValue] = DynamoFormat.xmap[JsValue, String]( + implicit val jsValue: DynamoFormat[JsValue] = DynamoFormat.xmap[JsValue, String]( x => Try(Json.parse(x)) match { case Success(y) => Right(y) case Failure(t) => Left(TypeCoercionError(t)) }, x => (Json.stringify(x)) ) - + implicit val trail: DynamoFormat[Trail] = deriveDynamoFormat[Trail] + implicit val userData: DynamoFormat[UserData] = deriveDynamoFormat[UserData] private lazy val userDataTable = Table[UserData](config.faciatool.userDataTable) private def updateClipboardContentByFieldName(articles: Option[JsValue], userEmail: String, fieldName: String) = {