Assets
Civilians asset handling serves the static resources – CSS, JavaScript, images, etc. –
of your application.
Introduction
Assets are static resources like CSS stylesheets, JavaScript code, images, etc.
used by your application. They are resources since they can be addressed by a URL;
they are static since they are (usually) not generated at runtime, but reside as files in the local file system.
Processing asset requests
a client does not care if a resource is static or dynamic. But internally processing of these requests is different:
- Requests for dynamic resources requires to create a Controller and call it to process the request.
- Requests for static resources will return the content of a server-side file.
By default Civilian first tries to route a request to a Controller.
If not possible it tries to find an asset for the request. If both fails the application sends
a not-found response.
Asset responses include a Last-Modified
header for the asset file date, and a max-age
header for 30 days. The If-Modified-Since
request header is evaluated and may
result in a 304 not modified response.
Asset locations
Civilians asset handling allows you to publish files from a local directories or (any other file trees) as
resources under the application path.
For example if directory
c:\myfiles
is published under the asset path
/files
in an application
with
path /myapp
, then the directory content will become available
as resources:
File |
Resource |
c:\myfiles\style.css |
/myapp/files/style.css |
c:\myfiles\js\script.js |
/myapp/files/js/script.js |
(Of course the asset path may be the root path
/
, publishing the asset files directly under the application root).
Publishing file assets from local directories
If deployed in a servlet container a Civilian has the directory layout of a web application, i.e. consists of a root
web app directory, containing a
WEB-INF
subdirectory with
web.xml
civilian.ini
.
The most natural way to publish assets is to place their files in the web app directory (the Civilian runtime makes
sure that files from the WEB-INF folder are not accesible).
File |
Resource |
/tomcat/webapps/myapp/style.css |
/myapp/style.css |
/tomcat/webapps/myapp/js/script.js |
/myapp/js/script.js |
/tomcat/webapps/myapp/WEB-INF/web.xml |
403 forbidden |
You may also publish a subdirectory of the web app root, or any directory in the local file system, outside of your
web app structure. (The later feature comes in handy during development, when you want to skip a
deployment build).
Publishing Java resource files from the classpath
Java classpath resources can also be published as web resources. For security reasons only Java resources with certain
non-empty prefixes may be published.
If for example Java resources beginning with
"/civassets"
are published under the asset path
/civ
in an application with path
/myapp
, then these Java resources become available as web resources:
File |
Resource |
jar:civilian.jar//civassets/admin/admin.css |
/myapp/civ/admin/admin.css |
/tomcat/webapps/myapp/WEB-INF/classes/civassets/style.css |
/myapp/civ/style.css |
Implementing own asset locations
Asset locations are represented as instances of the
AssetLocation class. If you need an additional asset retrieval
besides directories or Java resources, you could implement your own AssetLocation and install an instance during
asset configuration (see below).
Caching
Civilian maintains an asset cache and keeps smaller assets in memory to allow for fast responses.
(It also monitors and detects changes in assets files, and updates the cache accordingly).
Asset service
All the different asset locations used by an application and the asset cache are organized as pipeline
and made
available as
AssetService.
Asset encoding and content-types
An asset response contains a
Content-Type
header which includes an encoding parameter.
By default encoding of textual assets equals the application
encoding (which by default is UTF-8).
It is a good idea to serve all HTML pages and textual assets in the same encoding.
Additionally you can specify different encodings for every asset location.
The ContentLookup of the context is used to derive content-types from file extensions.
In a servlet environment this is implemented with a call to ServletContext.getMimeType()
and therefore uses
the content-type configuration of the servlet container.
Configuration
By default Civilian does not serve any assets. You must explicitly configure the asset locations
of an application via settings in
civilian.ini
or during application setup.
Configuration in civilian.ini
To define a single asset location for an application with id
myapp
, add a line to
civilian.ini
app.myapp.asset.location = <definition>
For multiple locations, add
app.myapp.asset.location.0 = <definition 0>
app.myapp.asset.location.1 = <definition 1>
...
The location definition consists of the location type, an optional parameter and
an optional path relative to the application path:
<definition> ::= <type> ( ':
' <param> )? ( '->
' <path> )?
<type> ::= dir
| res
| civres
The location type dir
denotes a directory containing assets files. If it has no param it equals
the directory where the application is deployed, if the param is an relative directory
then it is the corresponding subdirectory, else it is interpreted as absolute directory.
|
maps to directory |
app.myapp.asset.location.0 = dir |
→ /tomcat/webapps/myapp |
app.myapp.asset.location.1 = dir:gfx/images |
→ /tomcat/webapps/myapp/gfx/images |
app.myapp.asset.location.2 = dir:c:\repo\files |
→ c:\repo\files |
By default the assets are published under the application root path. To
publish under a
subpath
add that subpath to the definition:
definition / file |
URL |
app.myapp.asset.location.0 = dir |
|
/tomcat/webapps/myapp/css/style.css |
→ https://example.org/myapp/css/style.css |
app.myapp.asset.location.0 = dir -> /assets |
|
/tomcat/webapps/myapp/css/style.css |
→ https://example.org/myapp/assets/css/style.css |
The location type
res
serves
Java resources as assets. The required parameter is a
non-empty prefix of the served
Java resources.
civres
is an abbreviation
for
res:civassets -> /civilian
to serve resources from
civilian.jar
:
|
maps to resources |
app.myapp.asset.location.3 = res:assets |
→ ClassLoader.getResources("/myassets") |
app.myapp.asset.location.4 = civres |
→ ClassLoader.getResources("/civassets") |
Configuration during application startup
Alternatively and additionally you can
configure the asset
locations and cache behaviour during
application startup.
For advanced use you could also override Application.initAssets(AssetConfig)
to determine how the applications AssetService is constructed.
Build Process
JavaScript and CSS assets sent to the browser may often be direct development items.
But of course they can also be the result of some build process
- CSS stylesheets can be generated from LESS or SASS files,
- JavaScript can be generated from Coffeescript files,
- JavaScript or stylesheet files can be minified, uglified, beautified, ...
- Multiple JavaScript or stylesheet files can be concatenated
- etc.
Some web frameworks allow to include such a development process into their asset delivery pipeline.
This of course eases development: You simply edit the asset source(s) which get automatically transformed
into their final form when requested by a client.
Civilian decided to
not include such a facility because of the following reasons.
There are two main scenarios for an asset pipeline with inherent build capabilities:
- Minification and concatenation of multiple sources into a single JavaScript or CSS file
is typical for a production environment. But usually some build process is already needed
to create the deployment artifact (e.g. a WAR file) – the generation of asset files
can easily be integrated into that process.
- During development automatic transformation of coffee script, LESS, SASS, etc. files
into JavaScript or CSS files saves precious development time. But watcher tools
like Grunt are just perfect in
doing this: Just save your source, and the tool will almost immediately generate the transformed file,
which is then picked up by Civilians asset dispatch on the next request.