# Reference

This document explains the details of how Stapler "staples" your objects to URLs.

The way Stapler works is some what like Expression Language; it takes an object and URL, then evaluate the URL against the object. It repeats this process until it hits either a static resource, a view (such as JSP, Jelly, Groovy, etc.), or an action method.

This process can be best understood as a recursively defined mathematical function `evaluate(node,url)`. For example, the hypothetical application depicted in the "getting started" document could have an evaluation process like the following:

>     Scenario: browser sends "POST /project/jaxb/docsAndFiles/upload HTTP/1.1"

>        evaluate(<root object>, "/project/jaxb/docsAndFiles/upload")
>     -> evaluate(<root object>.getProject("jaxb"), "/docsAndFiles/upload")
>     -> evaluate(<jaxb project object>, "/docsAndFiles/upload")
>     -> evaluate(<jaxb project object>.getDocsAndFiles(), "/upload")
>     -> evaluate(<docs-and-files-section-object for jaxb>, "/upload")
>     -> <docs-and-files-section-object for jaxb>.doUpload(...)

The exact manner of recursion depends on the signature of the type of the `node` parameter, and the following sections describe them in detail. Also see a document in Hudson that explains how you can see the actual evaluation process unfold in your own application by monitoring HTTP headers.

## Evaluation of URL: Reference

This section defines the `evaluate(node,url)` function. Possible branches are listed in the order of preference, so when the given `node` and `url` matches to multiple branches, earlier ones take precedence.

> ### Notation

> We often use the notation `url[0], url[1], ...` to indicate the tokens of `url` separated by '/', and `url.size` to denote the number of such tokens. For example, if `url="/abc/def/"`, then `url[0]="abc", url[1]="def", url.size=2`. Similarly if `url="xyz"`, then `url[0]="xyz", url.size=1`

> List notation `[a,b,c,...]` is also used to describe `url`. Lower-case variables represent a single token, while upper-case variables represent variable-length tokens. For example, if we say `url=[a,W]` and the actual URL was "/abc/def/ghi", then `a="abc"` and `W="/def/ghi"`. If the actual URL was "/abc", then `a="abc"` and `W=""`.

### Stapler Proxy

`node` can implement the `StaplerProxy` interface to delegate the UI processing to another object. There's also a provision for selectively doing this, so that `node` can intelligently decide if it wants to delegate to another object.

Formally,

>     evaluate(node,url) := evaluate(target,url)   — if target instanceof StaplerProxy, target=node.getTarget(), and target!=null

### Index View

If there's no remaining URL, then a welcome page for the current object is served. A welcome page is a side-file of the `node` named `index.*` (such as `index.jsp`, `index.jelly`, etc.

Formally,

>     evaluate(node,[]) := renderView(node,"index")

### Action Method

If `url` is of the form "/fooBar/...." and `node` has a public "action" method named `doFooBar(...)`, then this method is invoked.

The action method is the final consumer of the request. This is is convenient for form submission handling, and/or implementing URLs that have side effects. Formally,

>     evaluate(node,[x,W]) := node.doX(...)

Stapler performs parameter injections on calling action methods.

### View

If the remaining URL is "/xxxx/...." and a side file of the node named `xxxx` exists, then this view gets executed. Views normally have their view-specific extensions, like `xxxx.jelly` or `xxxx.groovy`.

Formally,

>     evaluate(node,[x,W]) := renderView(node,x)

### Index Action Method

This is a slight variation of above. If there's no remaining URL and there's an action method called "doIndex", this method will be invoked. Formally,

>     evaluate(node,[]) := node.doIndex(...)

### Public Field

If `url` is "/fooBar/..." and `node` has a public field named "fooBar", then the object stored in `node.fooBar` will be evaluated against the rest of the URL. Formally,

>     evaluate(node,[x,W]) := evaluate(node.x,W)

### Public Getter Method

If `url` is "/fooBar/..." and `node` has a public getter method named "getFooBar()", then the object returned from `node.getFooBar()` will be evaluated against the rest of the URL.

Stapler also looks for the public getter of the form "getXxxx(StaplerRequest)". If such a method exists, then this getter method is invoked in a similar way. This version allows the get method to take sophisticated action based on the current request (such as returning the object specific to the current user, or returning null if the user is not authenticated.)

Formally,

>     evaluate(node,[x,W]) := evaluate(node.getX(...),W)

### Public Getter Method with a String Argument

If `url` is "/xxxx/yyyy/..." and `node` has a public method named "getXxxx(String arg)", then the object returned from `currentObject.getXxxx("yyyy")` will be evaluated against the rest of the URL "/...." recursively.

Formally,

>     evaluate(node,[x,y,W]) := evaluate(node.getX(y),W)

### Public Getter Method with an int Argument

Really the same as above, except it takes `int` instead of `String`.

>     evaluate(node,[x,y,W]) := evaluate(node.getX(y),W)   — if y is an integer

### Array

If `node` is an array and `url` is "/nnnn/...." where nnnn is a number, then the object returned from `node[nnnn]` will be evaluated against the rest of the URL "/...." recursively.

Formally,

>     evaluate(node,[x,W]) := evaluate(node[x],W)   — if node instanceof Object[]

### List

If `node` implements `java.util.List` and the URL is "/nnnn/...." where nnnn is a number, then the object returned from `node.get(nnnn)` will be evaluated against the rest of the URL "/...." recursively.

Formally,

>     evaluate(node,[x,W]) := evaluate(node.get(x),W)   — if node instanceof List

### Map

If `node` implements `java.util.Map` and the URL is "/xxxx/....", then the object returned from `node.get("xxxx")` will be evaluated against the rest of the URL "/...." recursively.

>     evaluate(node,[x,W]) := evaluate(node.get(x),W)   — if node instanceof Map

### Dynamic Action Method

If the current object has a public "action" method `doDynamic(StaplerRequest,StaplerResponse)`, then this method is invoked. From within this method, the rest of the URL can be accessed by `StaplerRequest.getRestOfPath()`. This is convenient for an object that wants to control the URL mapping entirely on its own.

The action method is the final consumer of the request.

Formally,

>     evaluate(node,url) := node.doDynamic(request,response)

### Dynamic Getter Method

If the current object has a public method `getDynamic(String,StaplerRequest,StaplerResponse)`, and the URL is "/xxxx/..." and then this method is invoked with "xxxx" as the first parameter. The object returned from this method will be evaluated against the rest of the URL "/...." recursively.

This is convenient for a reason similar to above, except that this doesn't terminate the URL mapping.

Formally,

>     evaluate(node,[x,W]) := evaluate(node.getDynamic(x,request,response),W)

### If None of the Above Works

... then the client receives 404 NOT FOUND error.

# Views

A Java class can have associated "views", which are the inputs to template engines mainly used to render HTML. Views are placed as resources, organized by their class names. For example, views for the class `org.acme.foo.Bar` would be in the `/org/acme/foo/Bar/` folder, like `/org/acme/foo/Bar/index.jelly` or `/org/acme/foo/Bar/test.jelly`. This structure emphasizes the close tie between model objects and views.

Views are inherited from base classes to subclasses.

### Jelly

Jelly script can be used as view files. When they are executed, the variable "it" is set to the object for which the view is invoked. (The idea is that "it" works like "this" in Java.)

For example, if your Jelly looks like the following, then it prints the name property of the current object.

    <html><body>
      My name is ${it.name}
    </body></html>