Full-stack Clojure web API

 

If you were building a Clojure web API what you you use?

I'm building one from scratch at the moment. I've been writing Clojure in my free time for a little over a year now, but with the multitude of Libraries to solve most problems, what would you choose?
The only constraint I really have is that I want to deploy it to a PAAS like Heroku.

This is what the tech stack looks like so far -

Testing - Midje and Ring-mock

Web server - Ring (I'll consider alternatives like http-kit if/when performance becomes an issue)
Routing - Compojure
I also have Ring-defaults and Ring-json in there for middleware.

For all things database related I have:
JDBC, Postgres, Korma and for migrations Ragtime. If I didn't have relational data I would be using MongoDB and Monger.

I still need to worry about data validation and probably contract tests. I've looked at Prismatic Schema (though, I prefer Validateur as it doesn't throw exceptions) for validation. I've looked at Janus and Pacto for contract testing.
I still also need to worry about authentication Friend is the only thing I've looked at so far in this space.

test.check and Liberator are two libraries I don't have a need for right now but will more than likely add them in when I do.

Would you do anything differently?

Pain points so far

I had one gotcha with Ragtime that took a while for me to figure out. You specify the SQL migrations folder in the project.clj like this - 

:ragtime { :migrations ragtime.sql.files/migrations
               :database "jdbc:postgresql://localhost:5432/cas" }

Where the keyword migrations gives you the "migrations" folder which is in the root directory for the project. I didn't quite want this setup and had a folder "database/migrations" and my project file instead had -

{ :migrations ragtime.sql.files/database/migrations } 

For some reason this gave me a null pointer exception every time, I didn't really look into why, I just moved my migrations folder to the project root directory, updated the project.clj and the problem went away.

I'm not completely happy with the database setup at the moment. Korma only allows you to pass in each part of the url separately, which is fine for Snap CI which has an environment variable for each part of the database connection (except db name). It's been a while since I've used Heroku but I think it only gives an environment variable with the JDBC url, which means I need to split it myself. Yes, a small pain but it seems like something the library should do for me.

The other thing that annoys me with Korma is aliasing fields in the database. There doesn't seem to be any decent way to alias a field during an insert. For example if I have a field "first_name" in the database I don't want my data to pass it around as {:first_name "Hugo"} I want the underscore to be a dash. During a select I can alias a field so it's not a problem using 

(fields [:first-name :first_name] :last)

But I can't setup that alias to always be on the table or alias at all during an insert, or at least no way I've tried seems to work. I tried the set-naming function but that didn't seem to do anything either. I seriously considered resorting back to MongoDB and Monger as that setup has always been far simpler for me to get working. The only reason I didn't is because I expect the data to be fairly relational.

Comments