There's always going to be only one top-level handler -- after all, even if at some conceptual level there are multiple handlers, the app needs to decide which one to apply to a given request somehow, so the routine which makes the choice becomes the top-level handler. So, the short answer is that you need to provide a function which will look at a request and hand it off to the appropriate handler among the several handlers inside your app; that function is the handler to be given to run-jetty
(or the equivalent).
Normally with Ring + Compojure you'd have some basic ("inner") handlers meant for handling particular URIs and some special-purpose handlers (say, for 404s) implemented as middleware. The former tend to be defined in defroutes
forms, while the latter are higher order functions.
The middleware handlers decide for themselves -- after looking at the request -- whether they want to return a response immediately or to delegate to handlers they are wrapped around. The route-based "inner" handlers are called upon for appropriate URIs and have the option of returning nil
to indicate that the request doesn't make sense to them (at which point the remaining route-based handlers are tried; if all nil
out, the final response is normally generated by some piece of middleware, possibly returning a 404).
I've written a lengthy answer concerning Compojure here; perhaps it might be of some help in getting the hang of Compojure's route-based handler definitions.