PlayFramework Evolutions & PostgreSQL Stored Procedures

If you have to create a stored procedure in your PlayFramework Database Evolution Script, make sure to properly escape your semicolons (by using two semicolons):

CREATE OR REPLACE FUNCTION user_insert_update_query_function()
RETURNS TRIGGER AS $$
BEGIN
  NEW.query := lower(NEW.firstname) || '|' || lower(NEW.lastname);;
  RETURN NEW;;
END;;
$$ LANGUAGE 'plpgsql';

PlayFramework: Serve a file from the classpath

Recently, I’ve implemented a Swagger-API with Play. As I’ve published a new version of the API, I wanted to make a CHANGELOG available.

So the question was, where to store this file.. a blog or some other external resource felt plainly wrong, so I decided to put it right next to the code.


 

 

[code language=”scala”]
class ChangeLogController (cc: ControllerComponents) extends AbstractController(cc) {

implicit val ec: ExecutionContext = cc.executionContext

def changeLog = cc.actionBuilder.apply { req =>
val clazz = this.getClass

val resource = Option(clazz.getResourceAsStream(“/de/some/package/structure/api/v1_1/CHANGELOG.txt”))

resource
.map(s => StreamConverters.fromInputStream(() => s))
.map(source => {
Result(
header = ResponseHeader(play.api.http.Status.OK, Map.empty, None),
body = HttpEntity.Streamed(source, None, Some(“text/plain”))
)
})
.getOrElse(Results.InternalServerError(“failed to load file from classpath”))
}

}
[/code]

Omnicharge Settings for MacBook Pro 15″ Mid 2015 Retina

I have a MacBook Pro 15″ Mid-2015 Retina. It uses a 85W MagSafe 2 Power Adapter, which is emitting max 4.25 Ampere at 20 Volts.




According to

https://omnicharge.zendesk.com/hc/en-us/articles/115000623608-Step-3-How-to-use-DC-output, that means,
I’ll have to configure my OmniCharge to 20V DC Output

 

To do this:

  • Turn the Omnicharge on
  • Double Click the Power button, Menu appears
  • Click the Power Button to enter DC Configuration
  • Use the UP-DOWN Arrows to select “Presets”, press Power Button to enter
  • Select 20V, use Power Button to select
  • Change to “Yes”, use Power Button to confirm
  • Done

 

Note to self: Akka-Streams: Zip first element of one source with every element of other source

The code looked like this:

val noIndexSource: Source[Set[ProductId], NotUsed] = Source.fromFuture(noIndexRepository.findAll()) // basically a Source.single()
val productsSource: Source[product.Product, NotUsed] = productRepository.getAllProducts(tenant)

after looking at the implementation of zipWithIndex, I came up with this solution:

val source: Source[(product.Product, Set[ProductId]), NotUsed] = noIndexSource
  .flatMapConcat(x => productsSource.statefulMapConcat { () ⇒
    elem ⇒ {
      val zipped = (elem, x)
      immutable.Iterable[(product.Product, Set[ProductId])](zipped)
    }
  })

val filteredSource = source.filterNot(x => x._2.contains(x._1.id)).map(_._1)

val f = filteredSource.via(flow).runWith(Sink.ignore)(materializer)

Do you know of a easier way to accomplish this? Let me know in the comments!

Note to self: Play-WS Scala send POST Request Multipart/Form-Data


import play.api.mvc.MultipartFormData._

val params: immutable.Iterable[DataPart] = Map(
"from" -> "xxx ",
"to" -> x.email,
"subject" -> "mySubject",
"text" ->
s"""Hallo!
| blablabla
""".stripMargin
).map { case (k, v) => DataPart(k, v) }

val par1 = Source.fromIterator(() => params.toIterator)

val f = wSClient
.url(configuration.getString("mailprovider.api.url").get + "/messages")
.withAuth("api", configuration.getString("mailprovider.api.key").get, WSAuthScheme.BASIC)
.post(par1)

Note to Self: PlayFramework split routes-file

File “conf/routes”:
->      /api                        api.Routes // focus on the big R!
->      /                           website.Routes
File “conf/api.routes”:
GET    /healthCheck/status                              api.controllers.HealthCheck.status
GET    /healthCheck/version                             api.controllers.HealthCheck.version
file “conf/website.routes”:
GET    /                         controllers.Home.index
GET    /robots.txt               controllers.Assets.at(path=”/public”, file=”robots.txt”)
GET    /assets/*file             controllers.Assets.at(path=”/public”, file)
GET    /profile                  controllers.Users.profile

 

 

 

 

Note to self: SBT Exclude (multiple) Dependencies (with Scala Version)

// pdf generation
val play2PDF = "it.innove" % "play2-pdf" % "1.5.1" excludeAll(
ExclusionRule(organization = "com.typesafe.play", name = "twirl-api_2.11"),
ExclusionRule(organization = "com.typesafe.play", name = "play-server_2.11"),
ExclusionRule(organization = "com.typesafe.play", name = "play-java_2.11"),
ExclusionRule(organization = "com.typesafe.play", name = "play-netty-server_2.11"),
ExclusionRule(organization = "com.typesafe.play", name = "play-logback_2.11")
)

Unfortunately, it’s required to hardcode the Scala Version into the Artifact name.. Bug https://github.com/sbt/sbt/issues/1518 is still open.
Additional note: ExclusionRule.artifact actually refers to the type of packaging.. like jar / pom / zip / etc.