This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # beginners (110)
- # boot (1)
- # cljs-experience (1)
- # clojure (58)
- # clojure-italy (4)
- # clojure-russia (1)
- # clojure-spec (4)
- # clojurescript (51)
- # cursive (2)
- # datomic (4)
- # devcards (4)
- # dirac (1)
- # figwheel (3)
- # fulcro (46)
- # hoplon (11)
- # om (4)
- # parinfer (7)
- # pedestal (1)
- # re-frame (11)
- # reagent (20)
- # specter (6)
- # unrepl (6)
so, I've had success with REST services and web routing and so on, but I'm a little mystified about how to build and organize services in clojure and put them in production...
suppose you had a car rental web app that, on the backend, has to check if the user is legit and enabled, if they have active payment, if they have your special frequent renter points, etc.
the thing that works for me is making an uberjar, then following all the normal steps for java
though I also kinda meant deployment... because if you have a raft of services doing all that stuff (in the java mindset)...
but a lot of the parts are similar to a java app or whatever - you can use a jwt or a cookie combined with a db
but how do I keep track of the sequence of things that need to be checked off for the prospective car rental... a series of things that have to be accomplished before, finally, something comes back to the endpoint...
well, in java, the PossibleCarRental thing is making a bunch of queries to API's and databases and so on (and makes DAO's to work with what's in the databases)...
(or if load balancing leads to the user talking to a different server, or whatever)
well, those are issues that java has... which is why I'm really trying to get into clojure... but I'm not understanding how it works yet in clojure...
right, so instead of an object, we'd have functions paramaterized by request-id and / or user id
so typically I find that the following steps are involved: a middleware that checks the auth and gathers data about the user, and attaches that as data to the request
then another step that optionally updates the db before sending a reply to theuser
it takes a handler function as an argument, and returns a new function that checks auth, bails if it's invalid, and attaches user specific data to the request before calling the target
the pattern usually looks like
(defn wrap-auth [handler] (fn rq-with-auth [request] (let [data (check-auth)] (if (bad? data) (fail request) (handler (assoc request :auth-data data)))))
so you can wrap the regular code in a layer that makes sure you bail if perms are lacking or whatever, and provides any context about the user the handler might need
so, similarly, a middleware could restore the partial state of a customer transaction (eg. a shopping cart)
for long requests... should/can you send something back to the client that says effectively 'thanks... working on it'...
sure, yeah- you might need a streaming api or websockets or whatever, but it's totally an option (I have requests that can last ten minutes or more, so we send continuous progress updates via a websocket to the frontend)
sente lib that gracefully falls back for clients that need to long poll ajax instead of websockets
another advantage with sente is that it uses transit to encode your data, so it's just plain clojure data structures on both ends of the socket
you don't need to worry about a conversion step as long as you aren't sending anything you shouldn't
(but still pay attention to data formats / structures across system boundaries, you still get a mess when you let that slip too much haha)
so, I couldn't figure out clojure at this level, relapsed into java for a hot minute, but can't live without in buffer repl development...
yeah - a lot of the java stuff has a direct clojure versrion (or, something much simpler that is reasonable once you have immutable data...)
I was/am still too busy remembering what conj does to different things to follow the exciting stuff.
on the other hand you can absolutely just make a spring app in java and then use clojure in all the request handlers
cool I wasn't suggesting clojure in a spring app was a good idea - just saying "hey, even that would work"
it's more the whole getting things into the database and back out and manipulating it all and so on that is hard for me...
well, that stuff tends to work nicely in clojure since there's a very straightforward mapping from clojure data to/from sql, as opposed to objects where things get really messy
actually, in Spring, I'm a little mystified too about how to handle the complex back end stuff...
it's more like, the more you get to know clojure and the more you get to know sql, the simpler that part is
there's a good book that covers this all in detail https://pragprog.com/book/dswdcloj2/web-development-with-clojure-second-edition
the author of that book is one of the main authors of tools in the clojure web stack
yeah, it uses reagent - it's using relatively up to date tools (cutting edge as of the publication date, and it's not like we have moved that far since then)
oh that stacks all good enough for me... in my case the stack isn't the important thing but learning it all... that said, the server side rendering I saw in most clojure tuts a year ago did wig me out a little
Playing with lein vs boot. Boot is twice as slow building the same uberjar - am I missing something obvious?
I tested my
encode function on the repl and it works as expected. Now I am working with reagent and a bit puzzled by this from Chrome console:
(prn "testing encode:" (encode "testing" "test")) ;;> "testing encode:" "" (prn "testing encode:" (type encode)) ;;> "testing encode:" #object[Function] (prn "testing encode:" (type (encode "testing" "jordan"))) ;;> "testing encode:" #object[String]