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.

Reply via email to