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.