blob: a29ca5b46c793c536c8a715b711a0d95a8f0998a [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
{8.0.0-new, 8.1.2-deprecated}
Config
<p>
In {@doc juneau-microservice-core.Config}, we described how to associate a configuration file with your
microservice.
In this section we describe how that configuration can be used to customize the behavior or your REST resource
classes.
</p>
<p>
The most common usage for the configuration file is to reference values using the {@link oaj.config.vars.ConfigVar $C} variable in annotations.
For example, the {@link oajr.BasicRestConfig} interface that defines the annotations that control the look-and-feel of
classes that extend from {@link oajr.BasicRestServlet} use several <c>$C</c> variables to externalize values:
</p>
<p class='bpcode w800'>
<ja>@Rest</ja>(
...
<jc>// HTML-page specific settings</jc>
htmldoc=<ja>@HtmlDoc</ja>(
<jc>// Default page header contents.</jc>
header={
<js>"&lt;h1&gt;$R{resourceTitle}&lt;/h1&gt;"</js>, <jc>// Use @Rest(title)</jc>
<js>"&lt;h2&gt;$R{methodSummary,resourceDescription}&lt;/h2&gt;"</js>, <jc>// Use either @RestMethod(summary) or @Rest(description)</jc>
<js>"$C{REST/header}"</js> <jc>// Extra header HTML defined in external config file.</jc>
},
<jc>// 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).</jc>
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
<jc>// Default contents to add to the &lt;head&gt; section of the HTML page.
// Use it to add a favicon link to the page.</jc>
head={
<js>"&lt;link rel='icon' href='$U{$C{REST/favicon}}'/&gt;"</js>
},
<jc>// No default page footer contents.
// Can be overridden from external config file.</jc>
footer=<js>"$C{REST/footer}"</js>,
...
),
<jc>// These are static files that are served up by the servlet under the specified sub-paths.
// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"
// By default, we define static files through the external configuration file.</jc>
staticFiles=<js>"$C{REST/staticFiles}"</js>
)
<jk>public interface</jk> BasicRestConfig {}
</p>
<p>
These values in turn are pulled from the external configuration file shown below.
Note that the configuration file can also contain <c>$C</c> variables.
</p>
<p class='bpcode w800'>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<cc># Mappings to folders containing static files.</cc>
<cc># Can be in the working directory or in the classpath.</cc>
<ck>staticFiles</ck> = <cv>htdocs:files/htdocs</cv>
<cc># Stylesheet to use for HTML views.</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
</p>
<p>
Configuration files can also be accessed programmatically.
There are 3 primary ways of getting access to the config file:
</p>
<ul class='javatree'>
<li class='jm'>{@link oaj.microservice.Microservice#getConfig()}
<p>Any {@doc DefaultRestSvlVariables initialization-time variables} can be used.</p>
<li class='jm'>{@link oajr.RestContext#getConfig()}
<p>Any {@doc DefaultRestSvlVariables initialization-time variables} can be used.</p>
<h5 class='figure'>Example usage:</h5>
<p class='bcode w800'>
<cc>#----------------------------------</cc>
<cc># Configuration for MyHelloResource </cc>
<cc>#----------------------------------</cc>
<cs>[MyHelloResource]</cs>
<ck>greeting</ck> = <cv>Hello world!</cv>
</p>
<p class='bcode w800'>
<cc>#---------------------------------</cc>
<cc># Contents of MyHelloResource.java </cc>
<cc>#---------------------------------</cc>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyHelloResource <jk>extends</jk> BasicRestServlet {
<jk>private</jk> String <jf>greeting</jf>;
<jc>// Or access config file in servlet init method.</jc>
<ja>@Override</ja> <jc>/* Servlet */</jc>
<jk>public void</jk> init() {
Config c = getContext().getConfig();
<jk>this</jk>.<jf>greeting</jf> = c.getString(<js>"MyHelloResource/greeting"</js>);
}
}
</p>
<p>
Additional user-defined variables at the servlet level can be defined by adding a
{@link oajr.annotation.HookEvent#INIT} hook method
and using the {@link oajr.RestContextBuilder#vars(Class...)} method.
</p>
<li class='jm'>
{@link oajr.RestRequest#getConfig()}
- An instance method to access it from inside a REST method.
<p>Any {@doc DefaultRestSvlVariables initialization-time or request-time variables} can be used.</p>
<h5 class='figure'>Example usage:</h5>
<p class='bcode w800'>
<cc>#----------------------------------</cc>
<cc># Configuration for MyHelloResource</cc>
<cc>#----------------------------------</cc>
<cs>[MyHelloResource]</cs>
<ck>greeting</ck> = <cv>Hello $RP{person}!</cv> <cc>// $RP is RequestPathVar</cc>
<ck>localizedGreeting</ck> = <cv>$L{HelloMessage,$RP{person}}</cv> <cc>// $L is LocalizationVar with args</cc>
</p>
<p class='bcode w800'>
<cc>#---------------------------------</cc>
<cc># Contents of MyHelloResource.java </cc>
<cc>#---------------------------------</cc>
<ja>@Rest</ja>(
path=<js>"/hello"</js>,
messages=<js>"nls/Messages"</js>,
...
)
<jk>public class</jk> MyHelloResource <jk>extends</jk> BasicRestServlet {
<jd>/** Standard hello message. */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/{person}"</js>)
<jk>public</jk> String sayHello(RestRequest req) {
<jk>return</jk> req.getConfig().getString(<js>"MyHelloResource/greeting"</js>);
}
<jd>/** Hello message in users language. */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/localized/{person}"</js>)
<jk>public</jk> String sayLocalizedHello(RestRequest req) {
<jk>return</jk> req.getConfig().getString(<js>"MyHelloResource/localizedGreeting"</js>);
}
}
</p>
<p class='bcode w800'>
<cc>#---------------------------------------</cc>
<cc># Contents of nls/Messages_en.properties </cc>
<cc>#---------------------------------------</cc>
<ck>MyHelloResource.HelloMessage</ck> = <cv>Hello {0}!</cv>
</p>
<p>
Additional user-defined variables can be defined at this level by overriding the
{@link oajr.RestContextBuilder#vars(Class...)} method.
</p>
</ul>
<p>
That <l>sayLocalizedHello()</l> example might need some explanation since there's a lot going on there.
Here's what happens when an HTTP call is made to <l>GET /hello/localized/Bob</l>:
</p>
<ol class='spaced-list'>
<li>
The HTTP call matches the <l>/hello</l> path on the <l>MyHelloResource</l> class.
<li>
The HTTP call matches the <l>/localized/{person}</l> path on the <l>sayLocalizedHello()</l> method.
<li>
The request attribute <l>person</l> gets assigned the value <l>"Bob"</l>.
<li>
The call to <l>req.getConfig().getString("MyHelloResource/localizedGreeting")</l>
finds the value <l>"$L{HelloMessage,$RP{person}}"</l>.
<li>
The arguments in the <l>$L{}</l> variable get resolved, resulting in <l>"$L{HelloMessage,Bob}"</l>.
<li>
The <l>$L{}</l> variable gets resolved to the message <l>"Hello {0}!"</l> in the localized properties
file of the servlet based on the <l>Accept-Language</l> header on the request.
<li>
The arguments get replaced in the message resulting in <l>"Hello Bob!"</l>.
<li>
The resulting message <l>"Hello Bob!"</l> is returned as a POJO to be serialized to whatever content
type was specified on the <l>Accept</l> header on the request.
</ol>
<p>
This particular example is needlessly complex, but it gives an idea of how variables can be used
recursively to produce sophisticated results
</p>
<ul class='seealso'>
<li class='link'>{@doc juneau-config}
</ul>