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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.