I use a closure, but with a slight twist in handler definitions. I close over a "make-handler" fn with the system component.. which returns a middleware-wrapped, dispatcher fn; the thing that handles the routing logic to a particular handler fun. Each of my handlers are 2 arg fns: (fn [system request]) - so the dispatcher passes-in the system to the appropriate handler at request-time along with the request.
The system instance is defined in the "core" ns of my app as a "var", and I use the same approach Stuart does to deal with app state in a friendly way: stop/start and alter-var-root! - that's the only global state, and it's really only used for development purposes. I'm still working out some kinks with testing. I recently moved from Midje to clojure.test. I use a lot of reify and proxy for "mocking", but I'll gladly take this over with-redefs wherever possible. There's definitely room for improvement. For example, creating a "test system" etc.. - Matt On Saturday, August 9, 2014 9:50:54 AM UTC-4, Brendan Younger wrote: > > I've struggled with the same issue as you, Sven. In a web app, your > handlers wind up needing access to every other component in the system > because they are the first point of contact with the outside world. > > In my apps, I've done this one of two ways: > > 1. Close over the needed dependencies when creating the ring handlers. > (Instead of just associating it into the request map.) For example: > > (defn make-handler [db sched] > (routes > (GET "/" request ...code which uses the db....) > (POST "/" request ...code which uses the scheduler...))) > > 2. Make the system a global variable in your handler namespace. For > example: > > (def system (atom nil)) > > (defroutes all-the-routes > (GET "/" request ...do something with (:db @system)...)) > > As long as you don't let code further down the chain rely on having a > :system key in the request map or a system global variable, you're still > achieving pretty good separation of concerns. > > Brendan > > On Friday, August 8, 2014 7:16:49 AM UTC-4, Sven Richter wrote: >> >> Hi, >> >> I am trying to integrate Stuarts component library into my application. I >> am not sure if I use it correctly or do something else wrong or just have a >> wrong mindset. So I will explain how I am currently using it and the >> problem I see with it. >> >> I have three components: database, a scheduler and web application (note >> that my example is simplified to get faster to the point). These components >> are built like this: >> >> (component/system-map >> :database (db db-uri) >> :scheduler (component/using (scheduler) [:database]) >> :web-app (component/using (web-app) >> [:database >> :scheduler] )) >> >> And in my web-app I do something like this: >> >> (start [component] >> (let [db-conn (get-in web-app [:database :db-conn])] >> (assoc component :server >> (run-server (make-handler web-app db-conn) {:port >> port})))) >> >> And make-handler is a middleware that associates the database component >> into the request map. >> >> Now as I added the scheduler to my system it occured to me that I will >> have to associate the scheduler into the request map too to access it and I >> might have to do that for every other component that is coming along the >> road. >> So basically I am tying my web-app to to all these components and I am >> tying some components to other components (like scheduler component to the >> database component). >> >> And by tying this things together this way they do depend on each other >> and I cannot move them anymore. This came to my mind as I started thinking >> about microservices. >> >> So let's say I want to convert the scheduler into a restful microservice, >> it's hard to pass in a database connection into it via HTTP, so it seems >> like it's not decoupled enough. Does that make sense? >> >> Am I using it wrong? Is it ok to pass all kind of dependencies into the >> request map and shove it around in the web application? Any other >> suggestions / remarks? >> >> Best Regards, >> Sven >> > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.