deploying to heroku with compujure/ring/uberjar, baffled

612 views
Skip to first unread message

kurofune

unread,
Apr 3, 2014, 8:27:07 AM4/3/14
to comp...@googlegroups.com
I am nearing the end of Yogthos' "Web Development with Clojure" book, but am having trouble at the part when you deploy to Heroku. The app worked fine during development and runs fine with 'foreman start', both as a stand alone jar (after changing the main.clj -main function to port 5000) and with 'web: lein with-profile production trampoline ring server' in the Procfile. I have succeeded with 'git push heroku master' scaling and when I check the status using heroku ps, it says the app is running. But when I type heroku open, or navigate to the url (http://safe-wave-7010.herokuapp.com/), the front page won't load, although it allows me to navigate to the registration page, which doesn't work. If i deploy from the standalone jar file, it crashes with this error in my logs:

2014-04-03T11:52:28.948246+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path=/ host=safe-wave-7010.herokuapp.com request_id=b9e25951-744d-4dc4-b680-12a3e515b33c fwd="103.5.142.23" dyno= connect= service= status=503 bytes=

Everything works fine in development: registration, deletion, uploading, etc. I am really confused. I'd be grateful if someone could enlighten me: Below is some basic stuff in my files.

project.clj 
 
(defproject picture-gallery "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [compojure "1.1.6"]
                 [hiccup "1.0.5"]
                 [ring-server "0.3.1"]
                 [postgresql/postgresql "9.1-901-1.jdbc4"]
                 [org.clojure/java.jdbc "0.2.3"]
                 [com.taoensso/timbre "3.1.6"]
                 [com.postspectacular/rotor "0.1.0"]
                 [lib-noir "0.8.1"]
                 [http-kit "2.1.12"]]
  :main picture-gallery.main
  :min-lein-version "2.0.0"
  :plugins [[lein-ring "0.8.7"]]
  :ring {:handler picture-gallery.handler/app
         :init picture-gallery.handler/init
         :destroy picture-gallery.handler/destroy}
  :profiles
  {:production
   {:ring
    {:open-browser? false, :stacktraces? false, :auto-reload? false}}
   :dev
   {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]]}}
  )
 
Procfile

 web: java -jar target/picture-gallery-0.1.0-SNAPSHOT-standalone.jar

main.clj

(ns picture-gallery.main
  (:use picture-gallery.handler
        [org.httpkit.server :only [run-server]]
        [ring.middleware file-info file])
  (:gen-class))

(defn -main [& [port]]
  (let [port (if port (Integer/parseInt port) 5000)]
    (run-server app {:port port})
    (println (str "You can view the site at http://localhost:" port))))
 

James Reeves

unread,
Apr 3, 2014, 9:04:18 AM4/3/14
to Compojure
See here: https://devcenter.heroku.com/articles/clojure-support#uberjar

It looks like you lack an :uberjar-name option in your project file.

- James


--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to compojure+...@googlegroups.com.
To post to this group, send email to comp...@googlegroups.com.
Visit this group at http://groups.google.com/group/compojure.
For more options, visit https://groups.google.com/d/optout.

kurofune

unread,
Apr 3, 2014, 9:32:04 AM4/3/14
to comp...@googlegroups.com, ja...@booleanknot.com
Thanks James, 

I tried out what you suggested, and everything went smoothly up to the very end and the app crashed again with the same error as before. Two things worth considering: 1) on the website I see '$JVM_OPTS' in the proc-file for the .jar file path. 2) During development, I was using a postgresql database stored on my hard-drive. I did add the plug-in as instructed and successfully located the connection settings on my dashboard, but I couldn't figure out how to reconfigure the db settings in my app, so I put it off. Could this be the source of my problem? Here is my current project.clj:

(defproject picture-gallery "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [compojure "1.1.6"]
                 [hiccup "1.0.5"]
                 [ring-server "0.3.1"]
                 [postgresql/postgresql "9.1-901-1.jdbc4"]
                 [org.clojure/java.jdbc "0.2.3"]
                 [com.taoensso/timbre "3.1.6"]
                 [com.postspectacular/rotor "0.1.0"]
                 [lib-noir "0.8.1"]
                 [http-kit "2.1.12"]]
  :main picture-gallery.main 
  :min-lein-version "2.0.0"
  :plugins [[lein-ring "0.8.7"]]
  :ring {:handler picture-gallery.handler/app
         :init picture-gallery.handler/init
         :destroy picture-gallery.handler/destroy}
  :profiles
  {:uberjar {:main picture-gallery.main, :aot :all}}
  )

kurofune

unread,
Apr 3, 2014, 9:49:46 AM4/3/14
to comp...@googlegroups.com, ja...@booleanknot.com
Also just tried this to similar effect. Should I delete the profiles section? Thank you for your help.  

...
:main picture-gallery.main 
  :min-lein-version "2.0.0"
  :plugins [[lein-ring "0.8.7"]]
  :ring {:handler picture-gallery.handler/app
         :init picture-gallery.handler/init
         :destroy picture-gallery.handler/destroy}
  :uberjar-name "picture-gallery-0.1.0-SNAPSHOT-standalone.jar"

James Reeves

unread,
Apr 3, 2014, 10:50:18 AM4/3/14
to Compojure
I'm not sure whether this is related to your issue, but my understanding is that Heroku uses the PORT environment variable to set the port, which your app doesn't appear to touch.

You may also be lacking an environment variable to set the URL for your Postgres connection.

- James

kurofune

unread,
Apr 3, 2014, 11:37:58 PM4/3/14
to comp...@googlegroups.com
Hey James,

Thanks for the suggestions. 'Web Dev with clj' mentions environment variables but I am not sure how to configure those from reading either that or the heroku docs. I spent last night researching the topic and I understand it in theory, but still don't understand what I should include in my project.clj to set the PORT environment var to something that will make my heroku deployed app load and function properly. I checked the URI path with the appropriate heroku command and that showed me the same URI that's on my dashboard when I log in, so I guess that's not the prob.

Jesse

Mark Nutter

unread,
Apr 5, 2014, 4:13:52 PM4/5/14
to comp...@googlegroups.com
Hi Jesse, I see I'm late to the conversation, but if you're still having problems, you might want to look at environ:


It sounds like you're trying to set the environment variables from inside your app, but that's the wrong way around. The idea is that Heroku sets up a database for you and then stores the connection parameters in some environment variables. Your app should *read* the environment variable(s) and use that value to set up your database connections inside the app. Use the environ.core/env function to easily read the environment variables.


Message has been deleted

kurofune

unread,
Apr 6, 2014, 11:29:16 AM4/6/14
to comp...@googlegroups.com
Hi mark, I used environ for my entire app and then got an error saying that the db-spec fn was turning up nil for my db keys. I had success deploying the sample heroku shouter app with a PostgreSQL db without using environ and thought for my simple purposes I could go without for my picture gallery as well. Reading the environ readme, I got a lot of info about ssl and what have you but not much specifically related to my heroku/db problem. I've read my book, the luminus and heroku docs, yogthos' blog posts and the jdbc docs too. As a beginner it's hard to pin down what I should do with the connection settings on my heroku dashboard and the idiomatic way to configure my env vars in leiningen by doing internet searches. I need a basic play by play, cause this seems like more than a simple debugging issue. I have a question up on stack. If you could have a look and help me to solve this I would be grateful.

http://stackoverflow.com/questions/22881632/deploying-to-heroku-with-clojure-project-production-environment-issues?noredirect=1#comment34919399_22881632

James Reeves

unread,
Apr 6, 2014, 2:39:29 PM4/6/14
to Compojure
I'm not sure what I can add on top of the documentation already around. Perhaps if I summarised...

First, you need to ensure your project file has the right options. It should have the following line:

  :min-lein-version "2.0.0"

It should also specify the uberjar name:

  :uberjar-name "your-app-standalone.jar"

Next, you need a "-main" function to launch your application. It should look something like:

  (ns your-app.main
    (:gen-class)
    (:require [ring.adapter.jetty :refer [run-jetty]]))

  (defn -main []
    (let [port (Integer. (System/getenv "PORT"))]
      (run-jetty handler {:port port})))

Create an :uberjar profile with the namespace your -main function is in:

  :profiles {:uberjar {:main your-app.main, :aot :all}}

Then add a Procfile with the following:

  web: java $JVM_OPTS -jar your-app-standalone.jar

The above tells Heroku how to compile and run your application. It summarises the information in: https://devcenter.heroku.com/articles/clojure-support

Next, your Postgres database. I'm not sure how far you've gotten in setting this up. The full instructions are here: https://devcenter.heroku.com/articles/heroku-postgresql

You'll want to check for the presence of a DATABASE_URL variable. Try running:

  heroku config

This will list all the environment variables in your application. There should be a DATABASE_URL variable with your Postgres connection URL in it.

Once you have the URL, you can pull it in from the environment with:

  (System/getenv "DATABASE_URL")

Use this URL to connect to your database. This kinda depends on what library you're using.

- James

kurofune

unread,
Apr 7, 2014, 5:50:27 AM4/7/14
to comp...@googlegroups.com
Daer James,

Big thanks. I have gone through my project again was careful to follow all of the points you mentioned in your last response. I can get it to deploy just fine, but when I open the page, I get a blank screen. I am able to navigate to some sub-pages, but they behave kind of buggy and weird. When I run the app as a standalone, locally, I get this error:

Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:454)
at java.lang.Integer.<init>(Integer.java:677)
at picture_gallery.main$_main.invoke(main.clj:9)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at picture_gallery.main.main(Unknown Source)

Here is a link to the heroku deployment: http://cryptic-lowlands-8934.herokuapp.com
Here is a link to the source on github: https://github.com/gamma235/picture-gallery

I really do appreciate you taking the time to help beginners and write an awesome library like environ, even if I don't know how to use it yet (That was you right?), and since I've started programming, you have been super helpful. 

Jesse

James Reeves

unread,
Apr 7, 2014, 6:20:47 AM4/7/14
to Compojure
Well, sure, that'll happen locally because you haven't set the port.

You can either set the port yourself, by running:

    PORT=3000 java -jar target/picture-gallery-0.1.0-SNAPSHOT-standalone.jar

Or you can add PORT=3000 to a .env file, and run it with Procfile.

It may also be useful to set a default port, like:

    (Integer. (or (System/getenv "PORT") "3000"))

Environ is a small library that makes working with environment variables a little easier. With environ, you could write the above as:

    (Integer. (env :port "3000"))

Where "env" is "environ.core/env". Environ also allows you to specify the environment through your project file, which is handy for development.

Could you describe how your pages act "buggy and weird"?

- James


--

kurofune

unread,
Apr 7, 2014, 8:36:57 PM4/7/14
to comp...@googlegroups.com, ja...@booleanknot.com
Right on about the PORT=3000 thing. I tried that and the standalone works fine locally, allowing me to register users, upload photos and delete accounts. When I navigate to the heroku link, though, to the "/register" path, it does render, but tells me that every name I try to register has already been taken (The error message that I put in for that actual case), even though it's a new database. If I just type heroku open at the CLI from the project root and go to the plain "/" url, I get a blank screen. My browser seems to be satisfied, showing it as loaded and rendered. I have tried it in different browsers of course, to the same effect. After I figure out what is going on, I intend to refactor the app, using JDBC 0.3.2 and then again using Korma and environ. 

kurofune

unread,
Apr 7, 2014, 10:50:07 PM4/7/14
to comp...@googlegroups.com, ja...@booleanknot.com
I redid the db using Korma, redeployed it and it suddenly worked! I still have no idea what the problem was. It might have had something to do with the fact that I was using JDBC 0.2.3 and no connection pooling. In any case, thanks again. 
Reply all
Reply to author
Forward
0 new messages