### 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. ```