<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<l:view contentType="text/html;charset=UTF-8">
<html>
<!-- fancy SPA -->
</html>
</l:view>
</j:jelly>
Jenkins filters view dispatch using the DispatchValidator
SPI in Stapler which implements some common default rules for distinguishing between views and fragments.
From the Jenkins Jelly tag library /lib/layout
, there is a Jelly tag, <l:view>
, which is used as the basis for defining a top level view and some optional parameters.
This tag is used and implied by the common Jelly tags <l:layout>
and <l:ajax>
which are the typical root Jelly elements used when defining views.
For views that don’t use l:layout
or l:ajax
, here’s an example of how to declare that:
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<l:view contentType="text/html;charset=UTF-8">
<html>
<!-- fancy SPA -->
</html>
</l:view>
</j:jelly>
Or using Groovy:
def l = namespace('/lib/layout')
l.view(contentType: 'text/html;charset=UTF-8') {
html {
// ...
}
}
Additionally, views named index
and views that set an HTTP content type header via <st:contentType>
are automatically considered views.
Some views do not follow these established patterns for one reason or another.
Views can be allowed or denied explicitly via the annotations @StaplerViews
and @StaplerFragments
respectively.
These annotations are applied to the model class that dispatches the views and override the above dispatch filtering logic.
For example, suppose Jenkins defines an abstract class BaseClass
which has views index
, configure
, create
, and delete
.
Implementation classes are expected to provide their own fragment view config
which gets included in configure
and create
.
This can be encoded explicitly in the model class:
@StaplerViews({"configure", "create", "delete"}) // index is implicit
@StaplerFragments("config")
public abstract class BaseClass {
...
}
By adding the annotations to Jenkins, implementation classes (typically from plugins) can be filtered explicitly via the parent annotations without updating the downstream code.
Implementation classes may further define additional views or fragments.
For example, suppose ExtendedClass
extends BaseClass
and adds its own optional fragment view advanced
which its implementation classes can include.
@StaplerFragments("advanced")
public class ExtendedClass extends BaseClass {
...
}
These annotations are provided in a standalone annotation dependency and can be included in a plugin’s dependencies:
<dependency>
<groupId>io.jenkins.stapler</groupId>
<artifactId>jenkins-stapler-support</artifactId>
<version>1.1</version>
</dependency>