public class ServerPagesBundle
extends ru.vyarus.dropwizard.guice.module.context.unique.item.UniqueGuiceyBundle
First of all global server pages support bundle must be installed (builder(), preferably directly in the
application class). This will activates dropwizard-views support (ViewBundle). Do not register
ViewBundle manually!
Each server pages application is also registered
as separate bundle (using app(String, String, String) or adminApp(String, String, String)).
Views configuration could be mapped from yaml file in main bundle:
ServerPagesBundle.ViewsBuilder.viewsConfiguration(ViewConfigurable). In order to fine tune configuration use
ServerPagesAppBundle.AppBuilder.viewsConfigurationModifier(String, ViewRendererConfigurationModifier) which could be used by
applications directly in order to apply required defaults. But pay attention that multiple apps could collide in
configuration (configure the same property)! Do manual properties merge instead of direct value set where possible
to maintain applications compatibility (e.g. you declare admin dashboard and main users app, which both use
freemarker and require default templates).
Renderers (pluggable template engines support) are loaded with service lookup mechanism (default for
dropwizard-views) but additional renderers could be registered with
ServerPagesBundle.ViewsBuilder.addViewRenderers(ViewRenderer...). Most likely, server page apps will be bundled as 3rd party
bundles and so they can't be sure what template engines are installed in target application. Use
ServerPagesAppBundle.AppBuilder.requireRenderers(String...) to declare required template engines for each application and
fail fast if no required templates engine. Without required engines declaration template files will be served like
static files when direct template requested and rendering will fail for rest-mapped template.
Each application could be "extended" using extendApp(String) bundle. This way
extra classpath location is mapped into application root. Pages from extended context could reference resources from
the main context (most likely common root template will be used). Also, extended mapping could override
resources from the primary location (but note that in case of multiple extensions order is not granted).
Obvious case for extensions feature is dashboards, when extensions add extra pages to common dashboard
application, but all new pages still use common master template.
Application work scheme: assets servlet is registered on the configured path in order to serve static assets
(customized version of dropwizard AssetServlet used which could
recognize both primary and extended locations). Special filter above servlet detects file calls (by extension,
but checks if requested file is template (and that's why list of supported templates is required)). If request
is not for file, it's redirected to rest endpoint in order to render view (note that direct template files will
also be rendered). Redirection scheme use application name, defined during bundle creation:
{rest prefix}/{app name}/{path from request}.
For example,
.bundles(SpaPageBundle.app("ui", "/com/assets/path/", "ui/").build())
Register application in main context, mapped to "ui/" path, with static resources in "/com/assets/path/"
classpath path. Internal application name is "ui". When browser request any file directly, e.g.
"ui/styles.css" then file "/com/assets/path/styles.css" will be served. Any other path is redirected to rest
endpoint: e.g. "ui/dashboard/" is redirected to "{rest mapping}/ui/dashboard.
@Template("dashboard.ftl")
@Path("ui/dahboard")
@Produces(MediaType.TEXT_HTML)
public class DashboardPage {
@GET
public DashboardView get() {
return new DashboardView();
}
}
Note that Template annotation on resource is required. Without it,
bundle will not be able to show path in console reporting. Also, configured template automatically applied
into view (so you don't have to specify template path in all methods (note that custom template path could
still be specified directly, when required). View class must extend
TemplateView. In all other aspects, it's pure dropwizard views.
Template annotation is jersey NameBinding marker
so you can apply request/response filters only (!) for template resources (see TemplateAnnotationFilter
as example).
Note that all resources, started from application name prefix are considered to be used in application.
extendApp(String) mechanism is used only to declare additional static
resources (or direct templates). But in order to add new pages, handled by rest resources you dont need to do
anything - they just must start with correct prefix (you can see all application resources in console just after
startup).
In order to be able to render direct templates (without supporting rest endpoint) special rest endpoint is registered which handles everything on application path (e.g. "ui/{file:.*}" for example application above). Only POST and GET supported for direct templates.
Bundle unifies custom pages handling to be able to use default 404 or 500 pages (for both assets and resources).
Use builder ServerPagesAppBundle.AppBuilder.errorPage(int, String) method to map template (or pure html)
to response code (to be shown instead).
Bundle could also enable filter from SpaBundle in order to support single
page applications routing (for cases when root page must be template and not just html, which makes direct usage of
SpaBundle useless).
Information about configured application may be acquired through GspInfoService
guice bean. But it could be used only after complete gsp initialization (between dropwizard run and jersey start).
| Modifier and Type | Class and Description |
|---|---|
static class |
ServerPagesBundle.ViewsBuilder
Global server pages support bundle builder.
|
| Modifier and Type | Field and Description |
|---|---|
static java.lang.String |
FILE_REQUEST_PATTERN
Default pattern for file request detection.
|
| Constructor and Description |
|---|
ServerPagesBundle(GlobalConfig config) |
| Modifier and Type | Method and Description |
|---|---|
static ServerPagesAppBundle.AppBuilder |
adminApp(java.lang.String name,
java.lang.String assetsPath,
java.lang.String uriPath)
Register application in admin context.
|
static ServerPagesAppBundle.AppBuilder |
adminApp(java.lang.String name,
java.lang.String assetsPath,
java.lang.String uriPath,
java.lang.ClassLoader loader)
Same as
adminApp(String, String, String) but with custom classloader to use for assets loading. |
static ServerPagesAppBundle.AppBuilder |
app(java.lang.String name,
java.lang.String assetsPath,
java.lang.String uriPath)
Register application in main context.
|
static ServerPagesAppBundle.AppBuilder |
app(java.lang.String name,
java.lang.String assetsPath,
java.lang.String uriPath,
java.lang.ClassLoader loader)
Same as
app(String, String, String) but with custom classloader to use for assets loading. |
static ServerPagesBundle.ViewsBuilder |
builder()
Creates global server pages support bundle which must be registered in the application.
|
static ServerPagesAppExtensionBundle.AppExtensionBuilder |
extendApp(java.lang.String name)
Extend registered application.
|
static ServerPagesAppExtensionBundle.AppExtensionBuilder |
extendApp(java.lang.String name,
java.lang.ClassLoader loader)
Same as
extendApp(String) but with custom classloader to use for assets loading. |
java.util.List<io.dropwizard.views.ViewRenderer> |
getRenderers()
Method is available for custom template detection logic (similar that used inside server pages filter)
or to validate state in tests.
|
java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.String>> |
getViewsConfig()
Method is available for custom views configuration state analysis logic (after startup) or to validate
state in tests.
|
void |
initialize(ru.vyarus.dropwizard.guice.module.installer.bundle.GuiceyBootstrap bootstrap) |
void |
run(ru.vyarus.dropwizard.guice.module.installer.bundle.GuiceyEnvironment environment) |
public static final java.lang.String FILE_REQUEST_PATTERN
public ServerPagesBundle(GlobalConfig config)
public static ServerPagesBundle.ViewsBuilder builder()
ViewBundle). If views bundle is manually declared in
application, it must be removed (to avoid duplicates). View bundle owning is required for proper configuration
and to know all used template engines (renderers).
After global support is registered, server pages applications may be declared with
app(String, String, String) and adminApp(String, String, String).
It is assumed that global bundles support is registered directly in the dropwizard application (and not transitively in some bundle) and server page applications themselves could be registered nearby (in dropwizard application) or in any bundle (for example, some dashboard bundle just registers dashboard application, assuming that global server pages support would be activated).
public static ServerPagesAppBundle.AppBuilder app(java.lang.String name, java.lang.String assetsPath, java.lang.String uriPath)
Application could be extended with extendApp(String) in another bundle.
NOTE global server pages support bundle must be installed with builder() in dropwizard application.
name - application name (used as servlet name)assetsPath - path to application resources (classpath); may be in form of package (dot-separated)uriPath - mapping urifor server pages applications global supportpublic static ServerPagesAppBundle.AppBuilder app(java.lang.String name, java.lang.String assetsPath, java.lang.String uriPath, java.lang.ClassLoader loader)
app(String, String, String) but with custom classloader to use for assets loading.
All additional registration through this builder (ServerPagesAppBundle.AppBuilder.attachAssets(String)) would also
be registered with provided class loader.
WARNING: custom class loader will be automatically supported for static resources, but template engine
may not be able to resolve template. For example, freemarker use class loader of resource class
serving view, so if resource class and view template are in the same class loader then it will work.
For sure direct template rendering (without custom resource class) will not work. Freemarker may be configured
to support all cases with custom template loader
(see ServerPagesBundle.ViewsBuilder.enableFreemarkerCustomClassLoadersSupport()) which must be configured
manually. Mustache is impossible to configure properly (with current mustache views renderer).
name - application name (used as servlet name)assetsPath - path to application resources (classpath); may be in form of package (dot-separated)uriPath - mapping uriloader - class loader to use for assets loadingfor server pages applications global supportpublic static ServerPagesAppBundle.AppBuilder adminApp(java.lang.String name, java.lang.String assetsPath, java.lang.String uriPath)
You can't register admin application on admin context root because there is already dropwizard
admin servlet AdminServlet.
Application could be extended with extendApp(String) in another bundle.
NOTE: global server pages support bundle must be installed with builder() in dropwizard application.
name - application name (used as servlet name)assetsPath - path to application resources (classpath)uriPath - mapping urifor server pages applications global supportpublic static ServerPagesAppBundle.AppBuilder adminApp(java.lang.String name, java.lang.String assetsPath, java.lang.String uriPath, java.lang.ClassLoader loader)
adminApp(String, String, String) but with custom classloader to use for assets loading.
All additional registration through this builder (ServerPagesAppBundle.AppBuilder.attachAssets(String)) would also
be registered with provided class loader.
WARNING: custom class loader will be automatically supported for static resources, but template engine
may not be able to resolve template. For example, freemarker use class loader of resource class
serving view, so if resource class and view template are in the same class loader then it will work.
For sure direct template rendering (without custom resource class) will not work. Freemarker may be configured
to support all cases with custom template loader
(see ServerPagesBundle.ViewsBuilder.enableFreemarkerCustomClassLoadersSupport()) which must be configured
manually. Mustache is impossible to configure properly (with current mustache views renderer).
name - application name (used as servlet name)assetsPath - path to application resources (classpath)uriPath - mapping uriloader - class loader to use for assets loadingfor server pages applications global supportpublic static ServerPagesAppExtensionBundle.AppExtensionBuilder extendApp(java.lang.String name)
For example, if we register application like this
ServerPagesBundle.app("ui", "/com/path/assets/", "/ui") it will server static resources only from
"/com/path/assets/" package. Suppose we want to add another page (with direct template) into the app:
ServerPagesBundle.extendApp("ui").attachAssets("/com/another/assets/"). Now assets will be searched in
both packages and if we have "/com/another/assets/page.tpl" then calling url "/ui/page.tpl" will render template.
Resource in extended location could override original app resource: e.g. if we have
"/com/another/assets/style.css" (extended) and "/com/path/assets/style.css" (original app) then
"/ui/style.css" will return extended resource file.
For new views addition, you may simply register new rest resources with prefix, used by application and it will detect it automatically (in example above app name is "ui").
If extended application is not registered no error will be thrown. This behaviour support optional application extension support (extension will work if extended application registered and will not harm if not).
Unlimited number of extensions could be registered for the same application (all extensions will be applied).
name - extended application namepublic static ServerPagesAppExtensionBundle.AppExtensionBuilder extendApp(java.lang.String name, java.lang.ClassLoader loader)
extendApp(String) but with custom classloader to use for assets loading.
All additional registration through this builder (ServerPagesAppBundle.AppBuilder.attachAssets(String)) would also
be registered with provided class loader.
WARNING: custom class loader will be automatically supported for static resources, but template engine
may not be able to resolve template. For example, freemarker use class loader of resource class
serving view, so if resource class and view template are in the same class loader then it will work.
For sure direct template rendering (without custom resource class) will not work. Freemarker may be configured
to support all cases with custom template loader
(see ServerPagesBundle.ViewsBuilder.enableFreemarkerCustomClassLoadersSupport()) which must be configured
manually. Mustache is impossible to configure properly (with current mustache views renderer).
name - extended application nameloader - class loader to use for assets loadingpublic java.util.List<io.dropwizard.views.ViewRenderer> getRenderers()
public java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.String>> getViewsConfig()
java.lang.NullPointerException - if views configuration is not yet created (views ot initialized)public void initialize(ru.vyarus.dropwizard.guice.module.installer.bundle.GuiceyBootstrap bootstrap)
public void run(ru.vyarus.dropwizard.guice.module.installer.bundle.GuiceyEnvironment environment)