#Stapler
Jenkins startup creates an instance of hudson.model.Hudson
(in WebAppMain
, which is a ServletContextListener
). It attaches the Hudson
instance to the ServletContext
, from where Stapler
can "get it".
Stapler handles all requests into Jenkins. The next section tries to make sense of that.
##Request Dispatch Mechanism
There's a nice visualization of how Stapler maps a Java Object Model hierarchy to a JEE Web App URL hierarchy in the What is Stapler document:
##WebApp Lots of stuff in this class. Among other things, it:
- Wraps the model (
Hudson
). - Holds a "classMap", mapping object types to
MetaClass
instances - Holds a
Facet
set -GroovyFacet
,JellyFacet
,JRebelFacet
.
##MetaClass
Holds meta info about a model object type. Holds a list of Dispatchers, which is build up (for a given type) by introspecting the object type in MetaClass.buildDispatchers()
.
MetaClass.buildDispatchers()
does the following:
- Methods that have a "do" name prefix add a
NameBasedDispatcher
impl. Can be optionally annotated with@WebMethod
so as to change the name mapping to something other than the one normally derived from the method name. - Methods that have a "js" name prefix add a
JavaScriptProxyMethodDispatcher
. - Methods annotated with
@JavaScriptMethod
add aJavaScriptProxyMethodDispatcher
. The annotation can override the mapping name. - If there's a method named "doIndex", a vanilla
Dispatcher
impl is added for that. - A
NameBasedDispatcher
impl is added for every field/property on the type. - A
NameBasedDispatcher
impl is added for every getter method on the type. Again,@WebMethod
can be optionally used to override the name mapping. - Methods that have a single arg (arg types
StaplerRequest
orString
orint
) method add aNameBasedDispatcher
impl. - Array,
List
orMap
types add aDispatcher
impls. - If there's a method named "doDynamic", a vanilla
Dispatcher
impl is added for that. - If there's a method with a name prefix of "getDynamic" and a single
String
arg, a vanillaDispatcher
impl is added for that.
Note: Between steps #3 and #4 (above), view dispatchers are added to the WebApp
's Facet
set, using the MetaClass
instance and the list of dispatchers gathered in the previous 3 steps. From what I can see however, none of the Facet impls that I encountered (GroovyFacet
, JellyFacet
, JRebelFacet
) seem to use the dispatcher list for anything.
Note: The NameBasedDispatcher
impls all do different funky things. See MetaClass.buildDispatchers()
.
Note: MetaClass
holds MetaClass
instances super
, so you can see the full graph.
Note: Between steps #8 and #9 (above), fallback dispatchers are added to the WebApp
's Facet
set, using the MetaClass
instance and the list of dispatchers gathered in the previous 8 steps. The Facet impls that I encountered (GroovyFacet
, JellyFacet
, JRebelFacet
) do nothing here i.e. don't seem to add anything.
##Serving static content
Stapler checks each request to see if it's a request for static content. It perfmors expiry checks on it etc etc. If it's not static content, it then proceeds to try serve it via invocation of dispatchers (matching tokens etc) via WebApp
, MetaClass
etc.
##StaplerProxy
##StaplerOverridable
##Facets (Groovy, Jelly etc) - View Dispatchers
##AdjunctManager Manages static content such as Javascript, CSS etc. Results in the <script> etc elements added to the response.
##Serving bound objects ('/$stapler/bound/...') What's this about?