Thursday, May 28, 2015

Tv Show Tracker - On Heroku

I recently decided that I should start testing out my tv show tracker website out in "the real web" instead of just local development. So to help me along I chose to use Heroku, which is a PaaS - platform as a service. The advantage of using a PaaS is that they manage your actual box, upgrades, security, etc. for you. All you have to do is build and deploy your site according to their guidelines.

After going through their documentation of how to deploy a Scala application, I have successfully deployed tv-show-tracker on Heroku. However, this was not as straight-forward as the documentation made it out to be - especially when I'm using spray instead of just a quick HTTP server like their example uses. So I thought I'd go through some of the things I had to do to get my site up and running on their platform.

First, lucky for me, I already had my site fully utilizing sbt so I had most of the config and dependencies working as they want you to. However, I did have to add an sbt plugin:
 addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.8.0")  
After that was added, I had to add the following to my build.sbt file:
 import NativePackagerKeys._  
 packageArchetype.java_application  
Heroku utilizes this native packager and foreman to run Scala applications which is not something I was doing when I would run it locally.

Secondly, I had issues connecting to my PostgreSQL database. They went through some of the steps, however I felt some things were lacking. In the end, my database connection looks like:
 val dbUri = new URI(System.getenv("DATABASE_URL"))  
 val username = dbUri.getUserInfo.split(":")(0)  
 val password = dbUri.getUserInfo.split(":")(1)  
 val db = Database.forURL(s"jdbc:postgresql://${dbUri.getHost}:${dbUri.getPort}${dbUri.getPath}", driver = "org.postgresql.Driver", user = username, password = password)  
This connection setup uses slick, where their example just had a regular database connection.

Next, I had issues seeing the data in my database. I was lucky enough to come across this stack overflow question which helped me solve my problem - look at my data on my local install of pgadmin. Now, the accepted answer is what I used to get it working, however not all steps are properly documented in that answer.

To get all of the information needed to fill out the pgadmin server, you first need to run:
 heroku config  
If you have the database add-on installed, it will spit out a database url that we need. We just need to know how to decipher this long url and break it into the individual parts:
 DATABASE_URL: postgres://user:password@server:port/database  
Once we know how the url is broken down (example above), you just plug each part into pgadmin (like the SO answer says) and you can see your data on your local install of pgadmin.

Lastly, I had issues with my site properly binding to the host and port and being able to hit the url from my computer.

For the port, I tried putting in 8080 and 5000 (from the example) but neither seemed to work. I eventually found this documentation which explains that I need to get the port from a system variable - PORT.

I also had issues with the hostname I was supposed to connect to. I tried "localhost" and my site's url but neither of those worked. Then I came across this SO answer which showed I needed to use "0.0.0.0". This allows the app to bind to the localhost and accept incoming traffic from my sites Heroku url.
So, in the end my connection looks like:
 val myPort = Properties.envOrElse("PORT", "8080").toInt // for Heroku compatibility  
 IO(Http) ? Http.Bind(service, interface = "0.0.0.0", port = myPort)  
This allows my app to get the proper port from Heroku or use a default of 8080 if I'm running locally.

All in all, this turned out pretty well seeing that I was able to go from my local setup to running on Heroku in just a few hours. There were a few hiccups along the way, but it seems like other people have ran into the issues I experienced before and I was able to use the answers given to them.

No comments:

Post a Comment