001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.server.view; 018 019import java.util.*; 020 021import org.apache.juneau.rest.server.*; 022import org.apache.juneau.rest.server.processor.*; 023 024/** 025 * Engine-agnostic contract for a server-side-rendered template return value from an 026 * {@link RestOp @RestOp}-annotated method. 027 * 028 * <p> 029 * A {@code View} carries the information a templating engine needs to render a response: the 030 * <b>template name</b> (relative to a base path supplied by the corresponding mixin), an 031 * <b>attribute map</b> exposed to the template, and an optional <b>response-headers</b> seam for 032 * setting {@code Content-Type}, {@code Cache-Control}, or other headers on the rendered response. 033 * 034 * <p> 035 * The interface is deliberately minimal and engine-agnostic. Concrete implementations live in the 036 * per-engine bridge modules ({@code juneau-rest-server-view-jsp}, future 037 * {@code juneau-rest-server-view-thymeleaf} / {@code -mustache} / {@code -freemarker}), each 038 * paired with a {@link ResponseProcessor} that detects its own {@code View} subtype and dispatches 039 * to the underlying templating engine. 040 * 041 * <h5 class='figure'>End-state usage:</h5> 042 * 043 * <p class='bjava'> 044 * <ja>@Rest</ja>(path=<js>"/app"</js>, mixins=JspMixin.<jk>class</jk>) 045 * <jk>public class</jk> AppResource <jk>extends</jk> RestServlet { 046 * 047 * <ja>@RestGet</ja>(<js>"/hello/{name}"</js>) 048 * <jk>public</jk> View hello(<ja>@Path</ja> String <jv>name</jv>) { 049 * <jk>return</jk> JspView.<jsm>of</jsm>(<js>"hello.jsp"</js>) 050 * .attr(<js>"name"</js>, <jv>name</jv>) 051 * .attr(<js>"ts"</js>, Instant.<jsm>now</jsm>()); 052 * } 053 * } 054 * </p> 055 * 056 * <h5 class='section'>Contract:</h5> 057 * 058 * <ul class='spaced-list'> 059 * <li>{@link #getTemplateName() getTemplateName()} — the template path the engine should 060 * render, typically relative to a mixin-configured base path (e.g. {@code "hello.jsp"} with 061 * base path {@code "/WEB-INF/views/"} resolves to {@code "/WEB-INF/views/hello.jsp"}). 062 * <b>Must never be {@code null}.</b> 063 * <li>{@link #getAttributes() getAttributes()} — key/value bindings exposed to the template 064 * (e.g. {@code ${name}} in a JSP, {@code th:text="${name}"} in a Thymeleaf template). Returns 065 * an immutable empty map when no attributes are bound. Must never be {@code null}. 066 * <li>{@link #getResponseHeaders() getResponseHeaders()} — optional response-headers map 067 * applied by the renderer before forwarding to the engine. Defaults to an empty map so most 068 * implementations don't need to override it; engines that want to set {@code Content-Type} 069 * or {@code Cache-Control} on the rendered response can populate this. 070 * </ul> 071 * 072 * <h5 class='section'>Stability:</h5> 073 * 074 * <p> 075 * This interface is the stable extension point for view modules. New methods will be added as 076 * {@code default}-bodied where possible to preserve backward compatibility with downstream view 077 * impls. 078 * 079 * <h5 class='section'>See Also:</h5><ul> 080 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JspViewSupport">JSP View Support</a> 081 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerComposition">REST Server — Mixins and Multi-Mount Paths</a> 082 * </ul> 083 * 084 * @since 10.0.0 085 */ 086public interface View { 087 088 /** 089 * The name of the template to render — typically a path relative to the 090 * mixin-configured base path. 091 * 092 * <p> 093 * For example, {@code "hello.jsp"} with a JSP mixin {@code basePath("/WEB-INF/views/")} 094 * resolves to {@code "/WEB-INF/views/hello.jsp"} on the request dispatcher. 095 * 096 * @return The template name. Never {@code null}. 097 */ 098 String getTemplateName(); 099 100 /** 101 * The attributes to expose to the template. 102 * 103 * <p> 104 * Each entry is forwarded to the templating engine as a named binding accessible from inside 105 * the template (e.g. {@code ${name}} in JSP / EL, {@code th:text="${name}"} in Thymeleaf). 106 * 107 * @return The attributes map. Never {@code null}; returns an immutable empty map when no 108 * attributes are bound. 109 */ 110 Map<String,Object> getAttributes(); 111 112 /** 113 * Optional response headers applied by the renderer before forwarding to the templating 114 * engine. 115 * 116 * <p> 117 * Typical use cases: setting {@code Content-Type} (e.g. {@code "text/html; charset=UTF-8"}) or 118 * {@code Cache-Control} on the rendered response. The default implementation returns an empty 119 * map so most {@code View} impls don't need to override it. 120 * 121 * @return An immutable map of headers to apply. Never {@code null}; defaults to an empty map. 122 */ 123 default Map<String,String> getResponseHeaders() { 124 return Map.of(); 125 } 126}