{title:'UI Customization', updated:'9.0.0'}

The HTML views of POJOs can somewhat be considered a rudimentary User Interface. In reality, a better term for them would be a Developer Interface as they're meant to be used primarily by developers and not end users. Despite that distinction, it is possible to 'brand' the HTML page to whatever you desire.

The sample root page below includes some default branding for Juneau and Apache:

| http://localhost:10000/helloWorld

The Juneau REST framework does not provide specific branding support (i.e. there is no concept of a brand icon). Instead, it just uses the existing open-ended API for defining branding via annotations on your REST classes.

| @Rest( | // Optional external configuration file. | config="$S{juneau.configFile}", | ) | @HtmlDocConfig( | | // Default stylesheet to use for the page. | // Can be overridden from external config file. | // Default is DevOps look-and-feel (aka Depression look-and-feel). | stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}", | | // Default page header contents. | header={ | "<h1>$RS{title}</h1>", // Use @Rest(title) | "<h2>$RS{operationSummary,description}</h2>", // Use either @RestOp(summary) or @Rest(description) | "$C{REST/header}" // Extra header HTML defined in external config file. | }, | | // Default contents to add to the <head> section of the HTML page. | // Use it to add a favicon link to the page. | head={ | "<link rel='icon' href='$U{$C{REST/favicon}}'/>" | }, | | // Basic page navigation links. | navlinks={ | "up: request:/.." | }, | | // No default page footer contents. | // Can be overridden from external config file. | footer="$C{REST/footer}" | ) | | public interface BasicUniversalConfig {}

| @Rest(...) | @HtmlDocConfig( | widgets={ | ContentTypeMenuItem.class, | ThemeMenuItem.class | }, | navlinks={ | "options: ?method=OPTIONS", | "$W{ContentTypeMenuItem}", | "$W{ThemeMenuItem}", | "source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java" | }, | aside={ | "<div style='max-width:400px' class='text'>", | " <p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>", | " <p>Resources can be nested arbitrarily deep through router pages.</p>", | " <p>Note the <span class='link'>options</span> link provided that lets you see the generated swagger doc for this page.</p>", | " <p>Also note the <span class='link'>sources</span> link on these pages to view the source code for the page.</p>", | " <p>All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.</p>", | " <p>Other features (such as this aside) are added through annotations.</p>", | "</div>" | }, | asideFloat="RIGHT" | ) | public class RootResources extends BasicRestServletGroup {...}

The default annotation values use {@link oaj.config.vars.ConfigVar $C} variables to pull in values from an optional external configuration file such as the one shown below:

| #======================================================================================================================= | # REST settings | #======================================================================================================================= | [REST] | | staticFiles = htdocs:files/htdocs | | # Stylesheet to use for HTML views. | theme = servlet:/htdocs/themes/devops.css | | headerIcon = servlet:/htdocs/images/juneau.png | headerLink = http://juneau.apache.org | footerIcon = servlet:/htdocs/images/asf.png | footerLink = http://www.apache.org | | favicon = $C{REST/headerIcon} | header = | <a href='$U{$C{REST/headerLink}}'> | <img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/> | </a> | footer = | <a href='$U{$C{REST/footerLink}}'> | <img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/> | </a>

The take-away here is that the "User Interface" is open-ended, lets you define pretty much anything you want through arbitrary HTML, and allows you either hardcode your interface inside annotations or pull them in via string variables from other places such as external config files.