### Example JSP Side File for BookStore
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
This is a sample index.jsp for the BookStore root object, demonstrating how to include static resources and loop through items.
```xml
...
<%-- side files can include static resources. --%>
Inventory
${i.value.title}
...
```
--------------------------------
### Jelly View Example
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Example of a Jelly script used as a view. The 'it' variable represents the object for which the view is invoked, similar to 'this' in Java.
```xml
My name is ${it.name}
```
--------------------------------
### Jelly View for BookStore Index
Source: https://context7.com/jenkinsci/stapler/llms.txt
This Jelly view template is rendered when GET / is requested. The 'it' variable represents the BookStore instance.
```xml
Book Store
Welcome to ${it.name}
Inventory
${entry.value.title}
Total items: ${it.items.size()}
```
--------------------------------
### Maven POM Setup for Stapler
Source: https://context7.com/jenkinsci/stapler/llms.txt
This XML configuration sets up the Maven POM file with Stapler dependencies and the maven-stapler-plugin. The plugin is required for @DataBoundConstructor support by capturing constructor parameter names at compile time.
```xml
org.kohsuke.stapler
stapler
1.257
org.kohsuke.stapler
stapler-jelly
1.257
org.kohsuke.stapler
maven-stapler-plugin
1.17
run
```
--------------------------------
### Jelly View for Book Index
Source: https://context7.com/jenkinsci/stapler/llms.txt
This Jelly view template is rendered when GET /items/b1 is requested. The 'it' variable represents the Book instance. It includes a shared footer.
```xml
${it.title}
SKU: ${it.sku}
```
--------------------------------
### Stapler View Evaluation Rule
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Defines the rule for rendering a view named 'x' when the URL starts with '/x' and a corresponding view file exists.
```java
evaluate(node,[x,W]) := renderView(node,x)
```
--------------------------------
### Data Binding with @DataBoundConstructor and @DataBoundSetter
Source: https://context7.com/jenkinsci/stapler/llms.txt
Use @DataBoundConstructor to enable Stapler to instantiate objects from JSON or form data. Employ @DataBoundSetter for optional properties that are set after construction. The example demonstrates binding a ServerConfig object from a JSON payload.
```java
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import net.sf.json.JSONObject;
public class ServerConfig {
private final String hostname;
private final int port;
private String description; // optional
private boolean ssl; // optional
@DataBoundConstructor
public ServerConfig(String hostname, int port) {
this.hostname = hostname;
this.port = port;
}
@DataBoundSetter
public void setDescription(String description) {
this.description = description;
}
@DataBoundSetter
public void setSsl(boolean ssl) {
this.ssl = ssl;
}
// Getters ...
}
public class ConfigEndpoint {
// POST /configure with body:
// {"hostname":"db.example.com","port":5432,"description":"Primary DB","ssl":true}
@POST
public HttpResponse doConfigure(StaplerRequest2 req)
throws ServletException {
JSONObject json = req.getSubmittedForm();
// Stapler calls new ServerConfig("db.example.com", 5432)
// then setDescription("Primary DB") and setSsl(true)
ServerConfig config = req.bindJSON(ServerConfig.class, json);
applyConfig(config);
return HttpResponses.ok();
}
}
```
--------------------------------
### Restricting HTTP Verbs with Annotations
Source: https://context7.com/jenkinsci/stapler/llms.txt
Use annotations like @GET, @POST, @PUT, and @DELETE to restrict web methods to specific HTTP verbs.
```APIDOC
## GET /item
### Description
Retrieves an item based on its SKU. Only responds to GET requests.
### Method
GET
### Endpoint
/item
### Parameters
#### Query Parameters
- **sku** (string) - Required - The SKU of the item to retrieve.
### Request Example
(No request body specified)
### Response
#### Success Response (200)
Returns an OK response if the item is found.
#### Error Response (404)
Returns a not found response if the item is not found.
```
```APIDOC
## POST /item/create
### Description
Creates a new item with the provided title and SKU. Only responds to POST requests.
### Method
POST
### Endpoint
/item/create
### Parameters
#### Query Parameters
- **title** (string) - Required - The title of the new item.
- **sku** (string) - Required - The SKU for the new item.
### Request Example
(No request body specified)
### Response
#### Success Response (200)
Redirects to the item's location.
```
```APIDOC
## DELETE /item/remove
### Description
Removes an item based on its SKU. Only responds to DELETE requests.
### Method
DELETE
### Endpoint
/item/remove
### Parameters
#### Query Parameters
- **sku** (string) - Required - The SKU of the item to remove.
### Request Example
(No request body specified)
### Response
#### Success Response (204)
Returns a No Content response if the item was successfully removed.
#### Error Response (404)
Returns a not found response if the item does not exist.
```
--------------------------------
### Stapler Action Method Evaluation Rule
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Defines the rule for invoking a public 'doX' method on a node when the URL starts with '/x'. This is used for form submissions and actions with side effects.
```java
evaluate(node,[x,W]) := node.doX(...)
```
--------------------------------
### Restricting HTTP Verbs with Annotations
Source: https://context7.com/jenkinsci/stapler/llms.txt
Restrict web methods to specific HTTP verbs using annotations like `@GET`, `@POST`, `@PUT`, and `@DELETE` from `org.kohsuke.stapler.verb`. The `@WebMethod` annotation can be used to specify the name of the web method.
```java
import org.kohsuke.stapler.verb.GET;
import org.kohsuke.stapler.verb.POST;
import org.kohsuke.stapler.verb.PUT;
import org.kohsuke.stapler.verb.DELETE;
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.QueryParameter;
public class ItemResource {
// GET /item — only responds to GET
@GET
@WebMethod(name = "item")
public HttpResponse doGetItem(@QueryParameter String sku) {
Item item = catalog.get(sku);
if (item == null) {
return HttpResponses.notFound(); // 404
}
return HttpResponses.ok();
}
// POST /item/create
@POST
public HttpResponse doCreate(@QueryParameter String title,
@QueryParameter String sku) {
catalog.put(sku, new Book(sku, title));
return HttpResponses.redirectTo(".");
}
// DELETE /item/remove
@DELETE
public HttpResponse doRemove(@QueryParameter String sku) {
if (!catalog.containsKey(sku)) {
return HttpResponses.notFound();
}
catalog.remove(sku);
return HttpResponses.status(204); // No Content
}
}
```
--------------------------------
### Jelly View with Internationalization
Source: https://context7.com/jenkinsci/stapler/llms.txt
This Jelly view demonstrates internationalization by using ${%KEY} syntax for simple key lookups and for keys with MessageFormat arguments. It also shows how to use a key within a JEXL expression.
```xml
${%Welcome}
${%ItemCount(it.items.size())}
```
--------------------------------
### Stapler Evaluation Scenario
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Illustrates a recursive evaluation process for a POST request to upload a file, showing how Stapler breaks down the URL and delegates to appropriate methods.
```java
evaluate(, "/project/jaxb/docsAndFiles/upload")
-> evaluate(.getProject("jaxb"), "/docsAndFiles/upload")
-> evaluate(, "/docsAndFiles/upload")
-> evaluate(.getDocsAndFiles(), "/upload")
-> evaluate(, "/upload")
-> .doUpload(...)
```
--------------------------------
### Configure Stapler Servlet in web.xml
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
Add this XML to your WEB-INF/web.xml to enable the Stapler servlet container.
```xml
Stapler
org.kohsuke.stapler.Stapler
Stapler
/
```
--------------------------------
### StaplerResponse2 Utilities for Forwarding, Redirecting, and Serving Files
Source: https://context7.com/jenkinsci/stapler/llms.txt
StaplerResponse2 offers methods for forwarding requests, redirecting clients, serving static files with cache headers, and exposing beans as REST responses.
```java
public class FileServer {
public void doServe(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
// Forward to a view relative to 'this' object
rsp.forward(this, "preview", req);
// Redirect back to the referring page
rsp.forwardToPreviousPage(req);
// Send a URL-encoded safe redirect
rsp.sendRedirect2("/some/path?q=hello world");
// Serve a static resource with cache-control headers
URL resourceUrl = getClass().getResource("/static/logo.png");
long oneDay = 24 * 60 * 60 * 1000L;
rsp.serveFile(req, resourceUrl, oneDay);
// Serve a locale-specific version if available (e.g. logo_ja.png for Japanese)
rsp.serveLocalizedFile(req, resourceUrl, oneDay);
// Serve an InputStream as a named file (sets MIME type from filename)
InputStream data = openFileStream();
rsp.serveFile(req, data, lastModified, expiration, contentLength, "report.pdf");
// Expose a bean as JSON or XML remote API
rsp.serveExposedBean(req, myExportedBean, Flavor.JSON);
}
}
```
--------------------------------
### Map Access
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Use when the node implements java.util.Map and the URL segment is a key. Access is performed using the get(key) method, and the result is recursively evaluated.
```java
evaluate(node,[x,W]) := evaluate(node.get(x),W) — if node instanceof Map
```
--------------------------------
### List Access
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Use when the node implements java.util.List and the URL segment is a numeric index. Access is performed using the get(index) method, and the result is recursively evaluated.
```java
evaluate(node,[x,W]) := evaluate(node.get(x),W) — if node instanceof List
```
--------------------------------
### documentation Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Provides documentation for a Jelly tag file, used for generating schemas and documentation.
```APIDOC
## documentation
### Description
Documentation for a Jelly tag file. This tag should be placed right inside the root element once, to describe the tag and its attributes. Maven-stapler-plugin picks up this tag and generate schemas and documentations. The description text inside this tag can also use Textile markup.
```
--------------------------------
### `StaplerResponse2` — Key Response Utilities
Source: https://context7.com/jenkinsci/stapler/llms.txt
`StaplerResponse2` extends `HttpServletResponse` with convenience methods for forwarding, redirecting, serving static files with cache headers, and exposing beans as REST responses.
```APIDOC
## `StaplerResponse2` — Key Response Utilities
`StaplerResponse2` extends `HttpServletResponse` with convenience methods for forwarding, redirecting, serving static files with cache headers, and exposing beans as REST responses.
```java
public class FileServer {
public void doServe(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
// Forward to a view relative to 'this' object
rsp.forward(this, "preview", req);
// Redirect back to the referring page
rsp.forwardToPreviousPage(req);
// Send a URL-encoded safe redirect
rsp.sendRedirect2("/some/path?q=hello world");
// Serve a static resource with cache-control headers
URL resourceUrl = getClass().getResource("/static/logo.png");
long oneDay = 24 * 60 * 60 * 1000L;
rsp.serveFile(req, resourceUrl, oneDay);
// Serve a locale-specific version if available (e.g. logo_ja.png for Japanese)
rsp.serveLocalizedFile(req, resourceUrl, oneDay);
// Serve an InputStream as a named file (sets MIME type from filename)
InputStream data = openFileStream();
rsp.serveFile(req, data, lastModified, expiration, contentLength, "report.pdf");
// Expose a bean as JSON or XML remote API
rsp.serveExposedBean(req, myExportedBean, Flavor.JSON);
}
}
```
```
--------------------------------
### BookStore Class with getItems Method
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
This Java class demonstrates a getItems method that returns a map of items, which Stapler can use to delegate URL requests.
```java
public class BookStore {
public Map/**/ getItems() {
return items;
}
...
```
--------------------------------
### Register WebAppMain Listener in web.xml
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
Add this XML to your WEB-INF/web.xml to ensure the container recognizes your WebAppMain listener class.
```xml
example.WebAppMain
```
--------------------------------
### Set Stapler Root Object with ServletContextListener
Source: https://context7.com/jenkinsci/stapler/llms.txt
Implement a ServletContextListener to set the root application object for Stapler when the web application initializes. This object will be bound to the root URL '/'.
```java
package com.example;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import org.kohsuke.stapler.Stapler;
public class WebAppMain implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
// Bind the root object to URL "/"
Stapler.setRoot(event, MyApp.theInstance);
}
@Override
public void contextDestroyed(ServletContextEvent event) {}
}
```
--------------------------------
### Default English Properties for BookStore
Source: https://context7.com/jenkinsci/stapler/llms.txt
Default English properties file for internationalization. Used for messages like 'Welcome' and 'ItemCount'.
```properties
# WEB-INF/side-files/example/BookStore/index.properties (default English)
Welcome=Welcome to our store
ItemCount=We have {0} items available
```
--------------------------------
### include Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Includes views of the object.
```APIDOC
## include
### Description
Tag that includes views of the object.
```
--------------------------------
### Handling HTTP Requests with Action Methods
Source: https://context7.com/jenkinsci/stapler/llms.txt
Public methods named `doFoo` handle the URL token `foo`. These methods act as terminal request handlers, similar to servlets. They can forward requests or redirect to other URLs.
```java
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse2;
import jakarta.servlet.ServletException;
import java.io.IOException;
public class BookStore {
// Handles: GET or POST /hello
public void doHello(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
req.setAttribute("systemTime", System.currentTimeMillis());
// Forward to WEB-INF/side-files/example/BookStore/helloJSP.jelly
rsp.forward(this, "helloJSP", req);
}
// Handles: POST /addItem — returns an HttpResponse object
public HttpResponse doAddItem(StaplerRequest2 req)
throws IOException, ServletException {
String title = req.getParameter("title");
if (title == null || title.isEmpty()) {
return HttpResponses.errorWithoutStack(400, "title is required");
}
String sku = "item-" + System.currentTimeMillis();
items.put(sku, new Book(sku, title));
// Redirect back to the store root
return HttpResponses.redirectTo(".");
}
// Handles: DELETE /item/b1 — full dynamic URL control
public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
String rest = req.getRestOfPath(); // e.g. "/b1"
String sku = rest.substring(1);
items.remove(sku);
rsp.setStatus(204);
}
}
```
--------------------------------
### Handling HTTP Requests with doXxx Methods
Source: https://context7.com/jenkinsci/stapler/llms.txt
Public methods named `doFoo` handle HTTP requests for the URL token `foo`. These methods act as terminal request handlers.
```APIDOC
## GET or POST /hello
### Description
Handles HTTP requests for the `/hello` endpoint, setting a system time attribute and forwarding to a JSP.
### Method
GET, POST
### Endpoint
/hello
### Request Example
(No request body specified)
### Response
#### Success Response (200)
(Forwarded to helloJSP.jelly)
```
```APIDOC
## POST /addItem
### Description
Handles POST requests to add an item to the store. Requires a 'title' parameter and returns an HttpResponse object.
### Method
POST
### Endpoint
/addItem
### Parameters
#### Query Parameters
- **title** (string) - Required - The title of the item to add.
### Request Example
(No request body specified, relies on query parameters)
### Response
#### Success Response (200)
Redirects to the store root.
#### Error Response (400)
- **message** (string) - 'title is required' if the title parameter is missing.
```
```APIDOC
## DELETE /item/{sku}
### Description
Handles DELETE requests to remove an item by its SKU. Provides dynamic URL control.
### Method
DELETE
### Endpoint
/item/{sku}
### Parameters
#### Path Parameters
- **sku** (string) - Required - The SKU of the item to remove.
### Request Example
(No request body specified)
### Response
#### Success Response (204)
No content, indicating successful deletion.
```
--------------------------------
### adjunct Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Writes out links to adjunct CSS and JavaScript files if they haven't been included already.
```APIDOC
## adjunct
### Description
Writes out links to adjunct CSS and JavaScript, if not done so already.
```
--------------------------------
### Register Root Object with ServletContextListener
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
Implement ServletContextListener to set the application's root object using Stapler.setRoot().
```java
package example;
import org.kohsuke.stapler.Stapler;
public class WebAppMain implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// BookStore.theStore is the singleton instance of the application
Stapler.setRoot(event,BookStore.theStore);
}
public void contextDestroyed(ServletContextEvent event) {
}
}
```
--------------------------------
### `StaplerRequest2` — Key Request Utilities
Source: https://context7.com/jenkinsci/stapler/llms.txt
`StaplerRequest2` extends `HttpServletRequest` with Stapler-specific helpers for URL traversal, view dispatch, cache control, and JSON/form binding.
```APIDOC
## `StaplerRequest2` — Key Request Utilities
`StaplerRequest2` extends `HttpServletRequest` with Stapler-specific helpers for URL traversal, view dispatch, cache control, and JSON/form binding.
```java
public class ItemHandler {
public void doProcess(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
// Get the unprocessed portion of the URL after this object
String rest = req.getRestOfPath(); // e.g. "/details/photos"
// Get the full ancestor chain leading to this object
List ancestors = req.getAncestors();
// ancestors.get(0) → root, ancestors.get(last) → "it" object
// Find a specific type in the URL traversal path
BookStore store = req.findAncestorObject(BookStore.class);
// Check HTTP caching (handles If-Modified-Since header)
long lastModified = getLastModifiedTimestamp();
if (req.checkIfModified(lastModified, rsp)) {
return; // 304 Not Modified already sent
}
// Get a RequestDispatcher for a named view of any object
RequestDispatcher rd = req.getView(this, "details");
if (rd != null) {
rd.forward(req, rsp);
}
// Bind submitted JSON form to a bean
JSONObject json = req.getSubmittedForm();
MyConfig config = req.bindJSON(MyConfig.class, json);
// Bind form parameters directly onto an existing bean
MyBean bean = new MyBean();
req.bindParameters(bean); // sets bean.setFoo(req.getParameter("foo"))
}
}
```
```
--------------------------------
### Japanese Properties for BookStore
Source: https://context7.com/jenkinsci/stapler/llms.txt
Japanese properties file for internationalization, providing localized messages for 'Welcome' and 'ItemCount'.
```properties
# WEB-INF/side-files/example/BookStore/index_ja.properties (Japanese)
Welcome=ストアへようこそ
ItemCount=商品が{0}点あります
```
--------------------------------
### Fallback URL Dispatch with StaplerFallback
Source: https://context7.com/jenkinsci/stapler/llms.txt
Implement StaplerFallback to provide a secondary object that Stapler attempts to use when the primary object cannot handle the URL. This is checked after all other dispatch strategies. The getStaplerFallback method should return the fallback object.
```java
import org.kohsuke.stapler.StaplerFallback;
public class PluggableResource implements StaplerFallback {
private final Object primaryHandler;
private final Object fallbackHandler;
public PluggableResource(Object primary, Object fallback) {
this.primaryHandler = primary;
this.fallbackHandler = fallback;
}
@Override
public Object getStaplerFallback() {
// If this object itself can't serve the URL, try fallbackHandler
return fallbackHandler;
}
// Primary action — serves GET /action
public HttpResponse doAction() {
return HttpResponses.ok();
}
}
// GET /resource/unknownToken → PluggableResource has no match
// → Stapler calls getStaplerFallback()
// → tries fallbackHandler for "unknownToken"
```
--------------------------------
### Stapler Index View Evaluation Rule
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Specifies the rule for serving a welcome page (index.*) when there is no remaining URL to evaluate.
```java
evaluate(node,[]) := renderView(node,"index")
```
--------------------------------
### Request Delegation with StaplerProxy
Source: https://context7.com/jenkinsci/stapler/llms.txt
Implement StaplerProxy to delegate URL processing to another object. This is useful for implementing interception logic, such as authorization checks, before the request is handled by the delegate. The getTarget method should return the object to which the request should be delegated.
```java
import org.kohsuke.stapler.StaplerProxy;
import org.kohsuke.stapler.HttpResponses;
public class SecuredResource implements StaplerProxy {
private final String requiredRole;
private final Object delegate;
public SecuredResource(String requiredRole, Object delegate) {
this.requiredRole = requiredRole;
this.delegate = delegate;
}
@Override
public Object getTarget() {
StaplerRequest2 req = Stapler.getCurrentRequest2();
if (!req.isUserInRole(requiredRole)) {
// null → 404; throw instead for 403
throw HttpResponses.forbidden();
}
// Delegate URL processing to the wrapped object
return delegate;
}
}
// Usage: wrap an admin panel so only "admin" role can access it
public class RootApp {
public Object getAdmin() {
return new SecuredResource("admin", AdminPanel.getInstance());
}
}
// GET /admin/... → SecuredResource.getTarget() checks role → delegates to AdminPanel
```
--------------------------------
### Forward Request to JSP in Java
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
Use this method within an action method to forward the request to a JSP file for rendering the response. This is useful for separating presentation logic from action handling.
```java
response.forward(this,"helloJSP",request);
```
--------------------------------
### Jelly View for Shared Item Footer
Source: https://context7.com/jenkinsci/stapler/llms.txt
This Jelly view provides a shared footer that can be inherited by other views, such as Book and CD. It demonstrates localized message retrieval.
```xml
```
--------------------------------
### Configure Stapler Servlet in web.xml
Source: https://context7.com/jenkinsci/stapler/llms.txt
Register the Stapler servlet as the default servlet in your web application's web.xml file. This configuration maps all incoming requests to the Stapler servlet.
```xml
Stapler
org.kohsuke.stapler.Stapler
Stapler
/
com.example.WebAppMain
```
--------------------------------
### adjunct Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Placeholder for adjunct tag documentation. No specific attributes or functionality are detailed in the source.
```APIDOC
## adjunct
### Description
Adjunct tag.
```
--------------------------------
### Generating HTTP Responses with HttpResponse and HttpResponses
Source: https://context7.com/jenkinsci/stapler/llms.txt
Action methods can return HttpResponse objects to decouple response generation. The HttpResponses factory provides convenient methods for common responses like redirects, errors, and OK statuses. Custom HttpResponse implementations can also be created for specific needs.
```java
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.HttpRedirect;
public class OrderController {
// Return HttpResponse directly (no void + rsp.sendRedirect)
public HttpResponse doCheckout(@QueryParameter String cartId) {
if (cartId == null) {
// Throw or return — both work
throw HttpResponses.error(400, "cartId is required");
}
if (!carts.containsKey(cartId)) {
return HttpResponses.notFound(); // 404
}
Order order = processCart(cartId);
if (order == null) {
return HttpResponses.errorWithoutStack(500, "Order processing failed");
}
// HTTP 302 redirect to order confirmation page
return HttpResponses.redirectTo("/orders/" + order.getId());
}
// Custom HttpResponse implementation
public HttpResponse doGetJson(@QueryParameter String sku) {
Item item = catalog.get(sku);
return (req, rsp, node) -> {
rsp.setContentType("application/json;charset=UTF-8");
rsp.setStatus(200);
rsp.getWriter().write("{\"sku\":\"" + item.getSku()
+ "\",\"title\":\"" + item.getTitle() + "\"}");
};
}
// Redirect to a context-relative path
public HttpResponse doGoHome() {
return HttpResponses.redirectViaContextPath("/dashboard");
}
}
```
--------------------------------
### redirect Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Sends an HTTP redirect to a specified URL.
```APIDOC
## redirect
### Description
Sends HTTP redirect.
### Attributes
#### url (required)
* **type**: String
* **description**: Sets the target URL to redirect to. This just gets passed to org.kohsuke.stapler.StaplerResponse2.sendRedirect2(String).
This tag does not accept any child elements/text.
```
--------------------------------
### header Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Adds an HTTP header to the response.
```APIDOC
## header
### Description
Adds an HTTP header to the response.
```
--------------------------------
### attribute Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Provides documentation for an attribute of a Jelly tag file, used within the 'documentation' tag.
```APIDOC
## attribute
### Description
Documentation for an attribute of a Jelly tag file. This tag should be placed right inside org.kohsuke.stapler.jelly.DocumentationTag to describe attributes of a tag. The body would describe the meaning of an attribute in a natural language. The description text can also use Textile markup.
```
--------------------------------
### copyStream Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Copies a stream as text.
```APIDOC
## copyStream
### Description
Copies a stream as text.
```
--------------------------------
### header Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Adds an HTTP header to the response. It requires a name and a value for the header.
```APIDOC
## header
### Description
Adds an HTTP header to the response.
### Attributes
* **name** (String) - Required - Header name.
* **value** (String) - Required - Header value.
```
--------------------------------
### HttpResponse Interface and HttpResponses Factory
Source: https://context7.com/jenkinsci/stapler/llms.txt
Action methods can return or throw HttpResponse objects to decouple response generation from the method body. HttpResponses provides common factory methods for creating responses.
```APIDOC
## `HttpResponse` Interface and `HttpResponses` Factory
Action methods can return or throw `HttpResponse` objects to decouple response generation from the method body. `HttpResponses` provides common factory methods.
```java
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.HttpRedirect;
public class OrderController {
// Return HttpResponse directly (no void + rsp.sendRedirect)
public HttpResponse doCheckout(@QueryParameter String cartId) {
if (cartId == null) {
// Throw or return — both work
throw HttpResponses.error(400, "cartId is required");
}
if (!carts.containsKey(cartId)) {
return HttpResponses.notFound(); // 404
}
Order order = processCart(cartId);
if (order == null) {
return HttpResponses.errorWithoutStack(500, "Order processing failed");
}
// HTTP 302 redirect to order confirmation page
return HttpResponses.redirectTo("/orders/" + order.getId());
}
// Custom HttpResponse implementation
public HttpResponse doGetJson(@QueryParameter String sku) {
Item item = catalog.get(sku);
return (req, rsp, node) -> {
rsp.setContentType("application/json;charset=UTF-8");
rsp.setStatus(200);
rsp.getWriter().write("{\"sku\":\"" + item.getSku()
+ "\",\"title\":\"" + item.getTitle() + "\"}");
};
}
// Redirect to a context-relative path
public HttpResponse doGoHome() {
return HttpResponses.redirectViaContextPath("/dashboard");
}
}
```
```
--------------------------------
### out Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Outputs a specified value with HTML escaping.
```APIDOC
## out
### Description
Tag that outputs the specified value but with escaping, so that you can escape a portion even if the org.apache.commons.jelly.XMLOutput is not escaping.
### Attributes
#### value (required)
* **type**: Expression
This tag does not accept any child elements/text.
```
--------------------------------
### doctype Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Writes out a DOCTYPE declaration.
```APIDOC
## doctype
### Description
Writes out DOCTYPE declaration.
```
--------------------------------
### Dynamic Action Method
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Use when an 'action' method 'doDynamic(StaplerRequest2, StaplerResponse2)' exists. This method is invoked to handle the rest of the URL mapping entirely within the method.
```java
evaluate(node,url) := node.doDynamic(request,response)
```
--------------------------------
### Parameter Injection with Annotations
Source: https://context7.com/jenkinsci/stapler/llms.txt
Stapler injects HTTP request parameters, headers, and ancestor objects directly into action method parameters using annotations.
```APIDOC
## GET /search?q=java&page=2
### Description
Handles search requests, injecting query parameters like 'q', 'filter', and 'page' automatically.
### Method
GET
### Endpoint
/search
### Parameters
#### Query Parameters
- **q** (string) - Required - The search query.
- **filter** (string) - Optional - A filter for the search results.
- **page** (int) - Required - The page number for the search results.
### Request Example
(No request body specified)
### Response
#### Success Response (200)
Returns an OK response.
```
```APIDOC
## Handling Secure Actions with @Header
### Description
Handles requests requiring authentication tokens and content type validation via HTTP headers.
### Method
(Not specified, assumed to be GET or POST based on context)
### Endpoint
/secureAction
### Parameters
#### Header Parameters
- **X-Auth-Token** (string) - Optional - The authentication token.
- **Content-Type** (string) - Required - The content type of the request.
### Request Example
(No request body specified)
### Response
#### Success Response (200)
Returns an OK response if the token is present.
#### Error Response (403)
Returns a forbidden response if the token is missing.
```
```APIDOC
## Adding Reviews with @AncestorInPath
### Description
Handles adding reviews to a book, injecting the ancestor `BookStore` object and the review text from query parameters.
### Method
(Not specified, assumed to be POST based on context)
### Endpoint
/bookstore/items/{sku}/reviews/add
### Parameters
#### Path Parameters
- **sku** (string) - Required - The SKU of the item to add a review to.
#### Query Parameters
- **reviewText** (string) - Required - The text of the review.
#### Ancestor Parameters
- **store** (BookStore) - Injected from the ancestor path.
### Request Example
(No request body specified)
### Response
#### Success Response (200)
Returns an OK response after adding the review.
```
--------------------------------
### Public Getter Method with Integer Argument
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Similar to the String argument version, but used when the public getter method accepts an integer argument. The integer is derived from the URL segment.
```java
evaluate(node,[x,y,W]) := evaluate(node.getX(y),W) — if y is an integer
```
--------------------------------
### contentType Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Sets the HTTP Content-Type header for the page. Requires a value for the content type.
```APIDOC
## contentType
### Description
Set the HTTP Content-Type header of the page.
### Attributes
* **value** (String) - Required - The content-type value, such as "text/html".
```
--------------------------------
### URL Binding via Public Getter Methods in Java
Source: https://context7.com/jenkinsci/stapler/llms.txt
Stapler uses public getter methods to map URL tokens to Java objects. A `getXxx()` method maps the token `xxx`, and collections like Maps can be accessed directly via their getter.
```java
// GET /store/items/b1 → bookStore.getItems().get("b1") → renders Book/index.jelly
// GET /store/items → renders BookStore/index.jelly with it.items available
public class BookStore {
private final Map items = new HashMap<>();
public static final BookStore theStore = new BookStore();
private BookStore() {
items.put("b1", new Book("b1", "The Life of Calvin McCoy"));
items.put("c1", new CD("c1", "Beethoven Sonatas"));
}
// Maps "/items" → items map; then "/items/b1" → items.get("b1")
public Map getItems() {
return items;
}
// Maps "/warehouse" → warehouseObject for further URL dispatch
public Warehouse getWarehouse() {
return Warehouse.getInstance();
}
}
public class Warehouse {
// GET /warehouse/shelf/3 → getShelf("3") → Shelf object
public Shelf getShelf(String id) {
return shelves.get(id);
}
}
```
--------------------------------
### compress Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
An outer-most wrapper tag to indicate that gzip compression is desirable for the output.
```APIDOC
## compress
### Description
Outer-most wrapper tag to indicate that the gzip compression is desirable for this output.
```
--------------------------------
### Define Action Method Signature in Java
Source: https://github.com/jenkinsci/stapler/blob/master/docs/getting-started.adoc
This is the standard signature for action methods in Stapler. These methods are invoked when a specific URL is requested and allow direct access to the 'it' object.
```java
public void do[Name]( StaplerRequest2 request, StaplerResponse2 response ) {
...
}
```
--------------------------------
### doctype Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Writes out a DOCTYPE declaration for the document. Requires publicId and systemId.
```APIDOC
## doctype
### Description
Writes out DOCTYPE declaration.
### Attributes
* **publicId** (String) - Required
* **systemId** (String) - Required
```
--------------------------------
### include Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Includes views of an object. It allows specifying the JSP to include, the object to use, and options for classloading and error handling.
```APIDOC
## include
### Description
Includes views of the object.
### Attributes
* **page** (String) - Required - Specifies the name of the JSP to be included.
* **it** (Object) - Optional - Specifies the object for which JSP will be included. Defaults to the "it" object in the current context.
* **from** (Object) - Optional - When loading the script, use the classloader from this object to locate the script. Otherwise defaults to "it" object.
* **class** (java.lang.Class) - Optional - When loading script, load from this class. By default this is "from.getClass()". This takes precedence over the org.kohsuke.stapler.jelly.IncludeTag.setFrom(Object) method.
* **optional** (boolean) - Optional - If true, not finding the page is not an error.
```
--------------------------------
### Custom URL Mapping with @WebMethod
Source: https://context7.com/jenkinsci/stapler/llms.txt
Assign custom URL names or expose a handler under multiple URL segments using @WebMethod(name=...). This is useful for non-identifier URL names or alternative endpoints.
```java
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.verb.GET;
import org.kohsuke.stapler.verb.POST;
public class ApiResource {
// Handles: GET /api/v1 (custom name with slash-like token)
@GET
@WebMethod(name = "v1")
public HttpResponse doGetV1() {
return HttpResponses.ok();
}
// Handles both: POST /submit and POST /save
@POST
@WebMethod(name = {"submit", "save"})
public HttpResponse doSubmitOrSave(@QueryParameter String data) {
process(data);
return HttpResponses.redirectTo(".");
}
// Handles: GET /api-info (hyphen is not a Java identifier)
@GET
@WebMethod(name = "api-info")
public HttpResponse doApiInfo() {
return HttpResponses.ok();
}
}
```
--------------------------------
### contentType Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Sets the HTTP Content-Type header of the page.
```APIDOC
## contentType
### Description
Set the HTTP Content-Type header of the page.
```
--------------------------------
### copyStream Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Copies a stream as text. It can accept input from a Reader, InputStream, File, or URL.
```APIDOC
## copyStream
### Description
Copies a stream as text.
### Attributes
* **reader** (Reader) - Optional
* **inputStream** (InputStream) - Optional
* **file** (File) - Optional
* **url** (URL) - Optional
```
--------------------------------
### parentScope Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Executes the tag's body in the parent scope, useful for creating local scopes.
```APIDOC
## parentScope
### Description
Executes the body in the parent scope. This is useful for creating a 'local' scope.
```
--------------------------------
### Stapler Index Action Method Evaluation Rule
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Specifies the rule for invoking a 'doIndex' method when there is no remaining URL, serving as an alternative to the index view.
```java
evaluate(node,[]) := node.doIndex(...)
```
--------------------------------
### Stapler Public Getter Method Evaluation Rule
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Defines the rule for evaluating the rest of the URL against the object returned by a public getter method 'getX'. This getter can optionally accept a StaplerRequest for dynamic behavior.
```java
evaluate(node,[x,W]) := evaluate(node.getX(...),W)
```
--------------------------------
### StaplerRequest2 Utilities for URL Traversal and Data Binding
Source: https://context7.com/jenkinsci/stapler/llms.txt
Utilize StaplerRequest2 for accessing URL path segments, ancestor objects, and binding submitted form data to beans. It also provides HTTP caching checks.
```java
public class ItemHandler {
public void doProcess(StaplerRequest2 req, StaplerResponse2 rsp)
throws IOException, ServletException {
// Get the unprocessed portion of the URL after this object
String rest = req.getRestOfPath(); // e.g. "/details/photos"
// Get the full ancestor chain leading to this object
List ancestors = req.getAncestors();
// ancestors.get(0) → root, ancestors.get(last) → "it" object
// Find a specific type in the URL traversal path
BookStore store = req.findAncestorObject(BookStore.class);
// Check HTTP caching (handles If-Modified-Since header)
long lastModified = getLastModifiedTimestamp();
if (req.checkIfModified(lastModified, rsp)) {
return; // 304 Not Modified already sent
}
// Get a RequestDispatcher for a named view of any object
RequestDispatcher rd = req.getView(this, "details");
if (rd != null) {
rd.forward(req, rsp);
}
// Bind submitted JSON form to a bean
JSONObject json = req.getSubmittedForm();
MyConfig config = req.bindJSON(MyConfig.class, json);
// Bind form parameters directly onto an existing bean
MyBean bean = new MyBean();
req.bindParameters(bean); // sets bean.setFoo(req.getParameter("foo"))
}
}
```
--------------------------------
### nbsp Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Writes out a non-breaking space character (' ').
```APIDOC
## nbsp
### Description
Writes out ' '.
This tag does not accept any child elements/text.
```
--------------------------------
### Public Getter Method with String Argument
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Use when the URL segment corresponds to a public getter method that accepts a String argument. The result of the getter is recursively evaluated against the rest of the URL.
```java
evaluate(node,[x,y,W]) := evaluate(node.getX(y),W)
```
--------------------------------
### Injecting Request Parameters with Annotations
Source: https://context7.com/jenkinsci/stapler/llms.txt
Stapler injects HTTP request parameters, headers, and ancestor objects directly into action method parameters using annotations. Use `@QueryParameter` for query string parameters, `@Header` for request headers, and `@AncestorInPath` for ancestor objects in the URL traversal path.
```java
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Header;
import org.kohsuke.stapler.AncestorInPath;
public class SearchEndpoint {
// GET /search?q=java&page=2
// Stapler injects "q" and "page" automatically from query string
public HttpResponse doSearch(
@QueryParameter(required = true) String q,
@QueryParameter(fixEmpty = true) String filter,
@QueryParameter int page) {
// q = "java", filter = null (if empty), page = 2
List- results = performSearch(q, filter, page);
return HttpResponses.ok(); // 200 OK
}
// Inject HTTP request header
public HttpResponse doSecureAction(
@Header("X-Auth-Token") String token,
@Header(value = "Content-Type", required = true) String contentType) {
if (token == null) {
return HttpResponses.forbidden(); // 403
}
return HttpResponses.ok();
}
// Inject ancestor object from URL traversal path
// e.g. URL: /bookstore/items/b1/reviews/add
// AncestorInPath finds the closest BookStore in the traversal chain
public HttpResponse doAddReview(
@AncestorInPath BookStore store,
@QueryParameter String reviewText) {
store.addReview(reviewText);
return HttpResponses.ok();
}
}
```
--------------------------------
### Dynamic Getter Method
Source: https://github.com/jenkinsci/stapler/blob/master/docs/reference.adoc
Use when a dynamic getter method 'getDynamic(String, StaplerRequest2, StaplerResponse2)' exists. This method is invoked with the URL segment as the first parameter, and its result is recursively evaluated.
```java
evaluate(node,[x,W]) := evaluate(node.getDynamic(x,request,response),W)
```
--------------------------------
### attribute Tag
Source: https://github.com/jenkinsci/stapler/blob/master/docs/jelly-taglib-ref.adoc
Documents an attribute of a Jelly tag file. This tag is used within DocumentationTag to describe attributes, including their name, usage, type, deprecation status, and introduction version.
```APIDOC
## attribute
### Description
Documentation for an attribute of a Jelly tag file. This tag should be placed right inside org.kohsuke.stapler.jelly.DocumentationTag to describe attributes of a tag. The body would describe the meaning of an attribute in a natural language. The description text can also use Textile markup
### Attributes
* **name** (String) - Required - Name of the attribute.
* **use** (String) - Optional - If the attribute is required, specify use="required". (This is modeled after XML Schema attribute declaration.) By default, use="optional" is assumed.
* **type** (String) - Optional - If it makes sense, describe the Java type that the attribute expects as values.
* **deprecated** (boolean) - Optional - If the attribute is deprecated, set to true. Use of the deprecated attribute will cause a warning.
* **since** (String) - Optional - Used to track when the attribute was added to the API surface.
```