public abstract class CachedAction extends AbstractAction
This is a base class for actions that take advantage of caching services. You can naturally also directly use the caching service without deriving from this class, but many common operations are already done here.
As described in the CacheService class, the basic idea in caching is that each cached page has a unique key identifying it. If in the future you need a page with a key that has already been cached, you can just return the cached page instead. The key itself is just any string that identifies the page. As such, everything that affects the page has to be somehow included in the key. This class contains a method, buildCacheKey, that takes a String map and builds a cache key based on that. The key will essentially be a serialisation of the Map. It is not required that you use this method to make the key but it is suitable for most situations.
Obviously it is not useful to cache actions that are highly dynamic and requests with the exact same key are unlikely to happen often.
To have an action use caching at all, the caching parameter in init parameters has to be set to true. By default caching is turned off. This is because many actions derive from this class that could potentially benefit from caching in some situations but not always.
When extending this class, you have to override at least the doOutput method, which writes the page into a stream. The stream might either be returned directly, or it may be written to a disk from where a copy is then automatically returned to the request.
You can also override returnOutput, which forwards data from an input stream into an HTTP response. The input stream might be coming from a cached file, or directly from do Output. The default implementation sets the HTTP headers possibly defined in AbstractAction and then copies the output directly. If you wish to set additional headers, such as content type or character encoding, the way to do it is to use writeMetadata in doOutput, which writes some extra information at the start of the stream, and then readMetadata at returnOutput, which reads it. Then you can add headers, or do anything else necessary, based on the metadata. The writing and reading of metadata must always be done symmetrically.
Modifier and Type | Class and Description |
---|---|
class |
CachedAction.OutputProvider
A class used to pass an output stream to the doOutput method.
|
Modifier and Type | Field and Description |
---|---|
protected CacheService |
cache
The cache service used to cache this action.
|
protected boolean |
caching
Is caching turned on.
|
protected java.util.concurrent.ExecutorService |
threadPool |
actionParamKey, handledActions, httpHeaders, isDefaultAction, replacements, replacementsInitialized, servletModule
engine, initScript, persistentObjects, scriptManager, startScript, stopScript
autoStart, isInitialized, isRunning, logging, loggingModule, moduleManager
Constructor and Description |
---|
CachedAction() |
Modifier and Type | Method and Description |
---|---|
static java.lang.String |
buildCacheKey(java.util.Map<java.lang.String,java.lang.String> params)
Builds a cache key from a Map of Strings.
|
protected abstract boolean |
doOutput(javax.servlet.http.HttpServletRequest req,
ModulesServlet.HttpMethod method,
java.lang.String action,
CachedAction.OutputProvider out,
User user)
Does the output that might be either cached or returned directly.
|
protected abstract java.lang.String |
getCacheKey(javax.servlet.http.HttpServletRequest req,
ModulesServlet.HttpMethod method,
java.lang.String action)
Should return a string that uniquely identifies this request.
|
java.util.Collection<Module> |
getDependencies(ModuleManager manager)
Returns all the modules this module depends on.
|
boolean |
handleAction(javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse resp,
ModulesServlet.HttpMethod method,
java.lang.String action,
User user)
Handles this action.
|
void |
init(ModuleManager manager,
java.util.HashMap<java.lang.String,java.lang.Object> settings)
Initialises the module.
|
static java.util.Map<java.lang.String,java.lang.String> |
readMetadata(java.io.InputStream in)
Use this to read the metadata written by writeMetadata method.
|
private static java.lang.String |
readUntilZero(java.io.InputStream in) |
protected void |
returnOutput(java.io.InputStream cacheIn,
javax.servlet.http.HttpServletResponse resp)
Writes a page read from an input stream into an HTTP servlet response.
|
void |
start(ModuleManager manager)
Starts the module.
|
void |
stop(ModuleManager manager)
Stops the module.
|
static void |
writeMetadata(java.util.Map<java.lang.String,java.lang.String> data,
java.io.OutputStream out)
Use this to write some metadata at the start of the cached file,
for example the mime type and character encoding of the file.
|
addHandledAction, doReplacements, handleRequest, isHandleAction, setActionParamKey, setHttpHeaders
getScriptEngine
isInitialized, isRunning, requireLogging, toString
protected CacheService cache
protected boolean caching
protected java.util.concurrent.ExecutorService threadPool
public java.util.Collection<Module> getDependencies(ModuleManager manager) throws ModuleException
Module
getDependencies
in interface Module
getDependencies
in class AbstractAction
manager
- The module manager handling this module.ModuleException
public void init(ModuleManager manager, java.util.HashMap<java.lang.String,java.lang.Object> settings) throws ModuleException
Module
Initialises the module. After constructor, this is the first method called in the life cycle of a module. It should not perform anything time consuming or anything with notable outside side effects. It should only read the parameters and initialise the module so that it can later be started. Note that a module being initialised doesn't mean that it necessarily will ever be started.
A ModuleException may be thrown if something vital is missing from the parameters or they are not sensible. In some cases you may not want to throw an exception even if vital initialisation information is missing. If, for example, it is possible that the module is initialised in some other way between the init and the start method calls. A ModuleException may also be thrown at the start method if the module is still not initialised.
init
in interface Module
init
in class AbstractAction
manager
- The module manager handling this module. You may keep a
reference to it if needed.ModuleException
public void start(ModuleManager manager) throws ModuleException
Module
start
in interface Module
start
in class AbstractAction
manager
- The module manager handling this module.ModuleException
public void stop(ModuleManager manager)
Module
stop
in interface Module
stop
in class AbstractAction
manager
- The module manager handling this module.public static java.lang.String buildCacheKey(java.util.Map<java.lang.String,java.lang.String> params)
params
- A map of key value pairs used in the cache key.protected abstract java.lang.String getCacheKey(javax.servlet.http.HttpServletRequest req, ModulesServlet.HttpMethod method, java.lang.String action)
req
- The HTTP request which, result of which is to be cached.method
- The method of the HTTP request.action
- The parsed action parameter from the request.protected void returnOutput(java.io.InputStream cacheIn, javax.servlet.http.HttpServletResponse resp) throws java.io.IOException
Writes a page read from an input stream into an HTTP servlet response. The input stream might be coming from a cached file, or directly from the doOutput method if caching is not in use. In any case, the contents of it need to be written to the response object. Note that any HTTP headers must be set before writing anything else.
If you used writeMetadata in doOutput, you have to override this method and use readMetadata correspondingly to read the metadata from the start of the stream. You can then, for example, set any HTTP headers you read from the metadata. After this, you can call this super implementation which will do the rest of the stream copying.
Make absolutely certain that the input stream is closed before returning from this method. Failing to do so may cause the caching service to become locked which can then lock the whole application. It is best to put the contents in a try-finally block and then call cacheIn.close in the finally part. Do this even if you call the super implementation as your code could possibly fail before reaching that part.
cacheIn
- resp
- java.io.IOException
public static void writeMetadata(java.util.Map<java.lang.String,java.lang.String> data, java.io.OutputStream out) throws java.io.IOException
java.io.IOException
private static java.lang.String readUntilZero(java.io.InputStream in) throws java.io.IOException
java.io.IOException
public static java.util.Map<java.lang.String,java.lang.String> readMetadata(java.io.InputStream in) throws java.io.IOException
java.io.IOException
protected abstract boolean doOutput(javax.servlet.http.HttpServletRequest req, ModulesServlet.HttpMethod method, java.lang.String action, CachedAction.OutputProvider out, User user) throws javax.servlet.ServletException, java.io.IOException, ActionException
Does the output that might be either cached or returned directly. The OutputProvider is used to get the output stream where the output should be written. Before you get this stream, you may abort the action by returning false but after the output stream is retrieved, you are committed to outputting the page that then might be cached for future use. Therefore you should do all the preparations first, and only then get the output stream when you know that you will be able to output something sensible.
If you opened the output stream using the output provider, you must make sure that the stream is properly closed. It is best to place all your code after this in a try-finally block and close the stream in the finally part. Failing to do this may cause the caching service to become locked, which in turn could potentially lock the whole application.
javax.servlet.ServletException
java.io.IOException
ActionException
public boolean handleAction(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp, ModulesServlet.HttpMethod method, java.lang.String action, User user) throws javax.servlet.ServletException, java.io.IOException, ActionException
AbstractAction
handleAction
in class AbstractAction
req
- The HTTP Request.resp
- The HTTP response.method
- The HTTP method of the request.action
- The parsed action id.user
- The logged in user, or null if not applicable.javax.servlet.ServletException
java.io.IOException
ActionException
Copyright 2004-2015 Wandora Team