gtag('config', 'G-0PFHD683JR');
Price Prediction

How to post Scala Play on Heroku

I was a web developer for years, but I haven’t touched on Java long ago-like the late 1990s. At that time, Java Development felt complicated: a lot of kettle and complex configurations. It was not a completely enjoyable experience to build simple web applications. So, when I recently started exploring Scala and playing frame, I was more curious than anything else. Has Java developer experience become better? Is it actually something I want to use today?

Scala works on the Java Virtual Machine, but it brings the construction of a more expressive and modern sentence on the table. It is often used in the development of the back interface, especially when the performance and the expansion are capable. Play is a Working framework for Scala, designed to be fast, interactive and friendly to developers. You are using SBT, a Scala Building Tool – almost similar to MAVEN or Grald in the Java world.

In this post, I will walk by setting up the main Scala Play app, operating it locally, then posted it on Heroku. I hope to show you how to run your application smoothly – without having to know a lot about JVM or how to play under the cover.

Submit the example application

To keep things simple, start with an existing sample project: Example Play Scala Rest API. It is a small application that offers some end points to create and recover blog publications. All data are stored in memory, so there is no database for its composition – ideal for testing and publishing experiences.

To facilitate matters on this roaming, I cloned that sample of the ribo and made some adjustments to prepare it to Heroku. You can continue using my Replo GitHub. This is not a ready -to -produce application, and this is the point. It is strong enough to explore how Play works and know what to run the Scala application and publish it actually.

Take a quick look at the symbol

Before we publish anything, let’s perform a quick tour of the application itself. It is a small code base, but there are some things that are worth referring to – especially if you are new on Scala or curious about how to compare the traditional Java. I have learned a lot about the privacy and generalities of the gameplay framework to build an application programming interface by reading this basic interpretation page. Here are some main points:

Class category for resource modeling

For this REST application programming interface, the primary supplier is the blog post, which contains idand linkand titleAnd body. The simplest way to model this is with the SCALA category that looks like this:

case class PostResource(
  id: String,
  link: String,
  title: String,
  body: String
)

This happens at the top app/v1/post/PostResourceHandler.scala (connection).

Clean and central guidance

the conf/routes HTTP files are required to a coordination device that is easy to read and change. It is closer to something like Express or Flask than the Java -based composition to XML. In our example, the file is just one line:

->         /v1/posts               v1.post.PostRouter

From there, the router in app/v1/post/PostRouter.scala (Link) Determines how different requests within this track map are to control methods.

override def routes: Routes = {
  case GET(p"/") =>
    controller.index

  case POST(p"/") =>
    controller.process

  case GET(p"/$id") =>
    controller.show(id)
}

This is very clear. A GET A request to the path of the path takes us to the console unit index The method, while POST The request takes us to process road. At the same time, a GET Request with a broom post id It will take us to show The method and pass along the given id.

Summary control units

This leads us to our console, in app/v1/post/PostController.scala (connection). Each end point is a way to return ActionWhich works with the json result using the built -in Play. For example:

def show(id: String): Action[AnyContent] = PostAction.async {
  implicit request =>
    logger.trace(s"show: id = $id")
    postResourceHandler.lookup(id).map { post =>
      Ok(Json.toJson(post))
    }
}

There is very little of boileplate – no separate interface ads or lengthy explanatory comments.

Json is dealt with implicit values

Play uses implicit values ​​to deal with and direct the JSON sequence. You are implicitly determined Format[PostResource] Using JSON’s macro units, then playing only knows how to turn things into JSON and return again. There is no need for manual analysis or lengthy formation. We see this in app/v1/post/PostResourceHandler.scala (connection):

object PostResource {
  /**
    * Mapping to read/write a PostResource out as a JSON value.
    */
    implicit val format: Format[PostResource] = Json.format
}

Building modern and expressive sentence

While wandering through the code, I see some of the most expressive Scala features at work – things like map operations and matching patterns with matching. The sentence construction looks new at the beginning, but it quickly feels a simplified mixture of Java and JavaScript.

Locally run the application

Before spreading in the cloud, it is always good to make sure that the app works locally. This helps us to arrest any clear problems and allows us to revolve around the application programming interface.

On my device, make sure I have Java and sbt Installed.

~/project$ java --version
openjdk 17.0.14 2025-01-21
OpenJDK Runtime Environment (build 17.0.14+7-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 17.0.14+7-Ubuntu-120.04, mixed mode, sharing)

~/project$ sbt --version
sbt version in this project: 1.10.6
sbt script version: 1.10.6

Then, I run the following from the root of my project:

~/project$ sbt run

[info] welcome to sbt 1.10.6 (Ubuntu Java 17.0.14)
[info] loading settings for project scala-api-heroku-build from plugins.sbt...
[info] loading project definition from /home/alvin/repositories/devspotlight/heroku/scala/scala-api-heroku/project
[info] loading settings for project root from build.sbt...
[info] loading settings for project docs from build.sbt...
[info]   __              __
[info]   \ \     ____   / /____ _ __  __
[info]    \ \   / __ \ / // __ `// / / /
[info]    / /  / /_/ // // /_/ // /_/ /
[info]   /_/  / .___//_/ \__,_/ \__, /
[info]       /_/               /____/
[info] 
[info] Version 3.0.6 running Java 17.0.14
[info] 
[info] Play is run entirely by the community. Please consider contributing and/or donating:
[info] https://www.playframework.com/sponsors
[info] 

--- (Running the application, auto-reloading is enabled) ---

INFO  p.c.s.PekkoHttpServer - Listening for HTTP on /[0:0:0:0:0:0:0:0]:9000

(Server started, use Enter to stop and go back to the console...)

With my local servant up and listening to the port 9000Open a new station and test the application programming interface by sending an order:

$ curl http://localhost:9000/v1/posts | jq

[
  {
    "id": "1",
    "link": "/v1/posts/1",
    "title": "title 1",
    "body": "blog post 1"
  },
  {
    "id": "2",
    "link": "/v1/posts/2",
    "title": "title 2",
    "body": "blog post 2"
  },
  {
    "id": "3",
    "link": "/v1/posts/3",
    "title": "title 3",
    "body": "blog post 3"
  },
  {
    "id": "4",
    "link": "/v1/posts/4",
    "title": "title 4",
    "body": "blog post 4"
  },
  {
    "id": "5",
    "link": "/v1/posts/5",
    "title": "title 5",
    "body": "blog post 5"
  }
]

Cute – good. It was quickly. After that, I want to play with some requests – recover and create a blog post.

$ curl http://localhost:9000/v1/posts/3 | jq

{
  "id": "3",
  "link": "/v1/posts/3",
  "title": "title 3",
  "body": "blog post 3"
}


$ curl -X POST \
    --header "Content-type:application/json" \
    --data '{ "title": "Just Another Blog Post", "body": "This is my blog post body." }' \
    http://localhost:9000/v1/posts | jq


{
  "id": "999",
  "link": "/v1/posts/999",
  "title": "Just Another Blog Post",
  "body": "This is my blog post body."
}

Preparing for publication to Hiroko

Well, we are ready to post Scala Play on Heroku. However, to be new on Scala and play, I am ready to strike some fast bumps. I want to cover these so that you can stay away from you.

to understand AllowedHostsFilter

When I run my application locally with sbt runI have no problems sending plexus requests and receiving responses. But as soon as I am in the cloud, I use the URL for the Heroku application, not localhost. For safety, Play has an enabled Hostsfilter, which means that you need to explicitly identify the hosts who can access the application.

I am amending conf/application.conf To include the following block:

play.filters.hosts {
  allowed = [
    "localhost:9000",
    ${?PLAY_ALLOWED_HOSTS}
  ]
}

This way, I can set a file PLAY_ALLOWED_HOSTS The composition variable for my Heroku application, add the URL to the Heroku app to the permitted hosts list.

Set

Play secretly requires a request for security. It is used for signature and encryption. You Be able to Set the secret of the request in conf/application.confBut this transmits it in your Ribo, and it is not a good practice. Instead, let’s put it at the time of operation based on the environmental formation variable. We add the following lines to conf/application.conf:

play.http.secret.key="changeme"
play.http.secret.key=${?PLAY_SECRET}

The first line appoints a virtual secret key, while the second line sets the secret to come from our composition variable, PLAY_SECRETIf appointed.

SBT operation for the translated duo operation

Finally, I want to talk a little sbt run. But first, let’s go back: In my first attempt to publish in Hiroko, I thought I would only play a server by carrying out Heroku. sbt run. When I did it, Dyno shadow it crashed. I did not realize how this situation was thick. It is dedicated to development, not production.

During that first attempt, I played Metrics Log-Rentime for my Heroku application. My application used more than 800 meters in memory – too much for Dyno Eco Little, which was only 512 meters. If you want to use sbt runYou need DYNO performance performance. This does not seem correct.

When I read Play documents about publishing an application, I realized that I should run my application through the translated duo created by playing over another matter, sbt stage. This version of my applied and much more effective application – to about 180MB. Assuming sbt stage I will work first, you just need to adjust my starting order to run the dual.

Why did you go with Hiroko?

I chose Heroku to run my Scala application as it removes a lot of friction. I do not need to form a server or install dependencies manually. Heroku is defined that this Scala app (by discovering a project/building. This means automatic dealing with things like accuracy of dependency and assembly by operation sbt stage.

For someone who only tries with Scala and play, this type of perfect scratch spreading. I can focus on understanding the frame and the code base without identifying the infrastructure. As soon AllowedHostsFilterSECRET, starting start – the publication was fast and repetitive.

Well, let’s go!

Publish the application on Hiroko

For publication, I installed Heroku Cli, and coincided with it heroku login. My first step is to create a new Hiroko app.

~/project$ heroku apps:create scala-blog-rest-api


Creating ⬢ scala-blog-rest-api... done
https://scala-blog-rest-api-5d26d52bd1e4.herokuapp.com/ | https://git.heroku.com/scala-blog-rest-api.git

Create a ProocFile

After that, I need to create Procfile This tells Heroku how to rotate my application. On the root of my project, I create the file, which contains this one line:

web: target/universal/stage/bin/play-scala-rest-api-example -Dhttp.port=${PORT}

Note that this is the matter to start the Heroku web process no sbt ruN. Instead, we implement the duo in target/universal/stage/bin/play-scala-rest-api-example. This is the duo that was collected after running sbt stage. where play-scala-rest-api-example The file name comes from? This was set in build.sbt. Ensure that the name is consistent between build.sbt and Procfile.

Also, we have set the port dynamically at the time of operation on the value of the environment variable PORT. Hiroko puts PORT The environment variable when our application begins, so we just need to tell our application what this port is.

Select JDK version

After that, I create a single line file called system.propertiesSelect the JDK version that I want to use in my application. Since I use Openjdk 17, my country system.properties The file looks like this:

java.runtime.version=17

Set the Heroku composition variables

To ensure that everything is in order, we need to set some composition variables for our application:

  • PLAY_SECRET: A series of our choice, what is required is at least 256 bits.
  • PLAY_ALLOWED_HOSTSURL Heroku, which is then included in AllowedHostsFilter Used in conf/application.conf.

We set our composition variables like this:

~/project$ heroku config:set \
  PLAY_SECRET='ga87Dd*A7$^SFsrpywMWiyyskeEb9&D$hG!ctWxrp^47HCYI' \
  PLAY_ALLOWED_HOSTS='scala-blog-rest-api-5d26d52bd1e4.herokuapp.com'

Setting PLAY_SECRET, PLAY_ALLOWED_HOSTS and restarting ⬢ scala-blog-rest-api... done, v2
PLAY_ALLOWED_HOSTS: scala-blog-rest-api-5d26d52bd1e4.herokuapp.com
PLAY_SECRET:        ga87Dd*A7$^SFsrpywMWiyyskeEb9&D$hG!ctWxrp^47HCYI

Payment code to Hiroko

With our Procfile It is created and our composition variables set, we are ready to pay our code to Heroku.

~/project$ git push heroku main


remote: Resolving deltas: 100% (14/14), done.
remote: Updated 95 paths from 4dc4853
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-24 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Play 2.x - Scala app detected
remote: -----> Installing Azul Zulu OpenJDK 17.0.14
remote: -----> Priming Ivy cache... done
remote: -----> Running: sbt compile stage
remote: -----> Collecting dependency information
remote: -----> Dropping ivy cache from the slug
remote: -----> Dropping sbt boot dir from the slug
remote: -----> Dropping sbt cache dir from the slug
remote: -----> Dropping compilation artifacts from the slug
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing...
remote:        Done: 128.4M
remote: -----> Launching...
remote:        Released v5
remote:        https://scala-blog-rest-api-5d26d52bd1e4.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/scala-blog-rest-api.git
 * [new branch]      main -> main

I love how I just need to create a file Procfile And set some composition variables, then Heroku is interested in its rest for me.

It’s time to test

All that remains to do is the Scala Play application test with some Curl requests:

$ curl https://scala-blog-rest-api-5d26d52bd1e4.herokuapp.com/v1/posts \
       | jq

[
  {
    "id": "1",
    "link": "/v1/posts/1",
    "title": "title 1",
    "body": "blog post 1"
  },
  {
    "id": "2",
    "link": "/v1/posts/2",
    "title": "title 2",
    "body": "blog post 2"
  },
  {
    "id": "3",
    "link": "/v1/posts/3",
    "title": "title 3",
    "body": "blog post 3"
  },
  {
    "id": "4",
    "link": "/v1/posts/4",
    "title": "title 4",
    "body": "blog post 4"
  },
  {
    "id": "5",
    "link": "/v1/posts/5",
    "title": "title 5",
    "body": "blog post 5"
  }
]

$ curl https://scala-blog-rest-api-5d26d52bd1e4.herokuapp.com/v1/posts/4 \
       | jq

{
  "id": "4",
  "link": "/v1/posts/4",
  "title": "title 4",
  "body": "blog post 4"
}

$ curl -X POST \
    --header "Content-type:application/json" \
    --data '{"title":"My blog title","body":"this is my blog post"}' \
    https://scala-blog-rest-api-5d26d52bd1e4.herokuapp.com/v1/posts \
    | jq

{
  "id": "999",
  "link": "/v1/posts/999",
  "title": "My blog title",
  "body": "this is my blog post"
}

API server works. Publishing was smooth and simple. I learned a lot about Scala and playing all the way. All in all … it was a good day.

conclusion

Jumping to Scala was not decades after Java – and used to build more web applications with Javascript – as I expected. I felt a brief and modern scala construction, worked with cases of cases and unexplained control units reminded me of a little of the patterns that I already use in Node.js. There is still an educational curve with the tools and how things are organized in playing – but in general, I felt friendly, not overwhelming.

Publishing on the cloud had a few turns, especially on how to play players with hosts and secrets and use memory in production. But as soon as I understood how these pieces worked, making the app live on Heroku clearly and directly. With some changes in the configuration and the appropriate startup matter, the process was clean and repetitive.

To build and publish Scala for the first time, I couldn’t request a smoother experience. Are you ready to try it?

Happy coding!

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button