**/
public boolean service(RequestContext context) throws ServletException, IOException
{
ApplicationServlet servlet = context.getServlet();
IRequestCycle cycle = null;
ResponseOutputStream output = null;
IMonitor monitor = null;
if (LOG.isDebugEnabled())
LOG.debug("Begin service " + context.getRequestURI());
if (_specification == null)
_specification = servlet.getApplicationSpecification();
// The servlet invokes setLocale() before invoking service(). We want
// to ignore that setLocale() ... that is, not force a cookie to be
// written.
_localeChanged = false;
if (_resolver == null)
_resolver = servlet.getResourceResolver();
try
{
setupForRequest(context);
monitor = getMonitor(context);
output = new ResponseOutputStream(context.getResponse());
}
catch (Exception ex)
{
reportException(Tapestry.getMessage("AbstractEngine.unable-to-begin-request"), ex);
throw new ServletException(ex.getMessage(), ex);
}
IEngineService service = null;
try
{
try
{
String serviceName;
try
{
serviceName = extractServiceName(context);
if (Tapestry.isBlank(serviceName))
serviceName = Tapestry.HOME_SERVICE;
// Must have a service to create the request cycle.
// Must have a request cycle to report an exception.
service = getService(serviceName);
}
catch (Exception ex)
{
service = getService(Tapestry.HOME_SERVICE);
cycle = createRequestCycle(context, service, monitor);
throw ex;
}
cycle = createRequestCycle(context, service, monitor);
monitor.serviceBegin(serviceName, context.getRequestURI());
// Invoke the service, which returns true if it may have changed
// the state of the engine (most do return true).
service.service(this, cycle, output);
// Return true only if the engine is actually dirty. This cuts down
// on the number of times the engine is stored into the
// session unceccesarily.
return _dirty;
}
catch (PageRedirectException ex)
{
handlePageRedirectException(ex, cycle, output);
}
catch (RedirectException ex)
{
handleRedirectException(cycle, ex);
}
catch (StaleLinkException ex)
{
handleStaleLinkException(ex, cycle, output);
}
catch (StaleSessionException ex)
{
handleStaleSessionException(ex, cycle, output);
}
}
catch (Exception ex)
{
monitor.serviceException(ex);
// Discard any output (if possible). If output has already been sent to
// the client, then things get dicey. Note that this block
// gets activated if the StaleLink or StaleSession pages throws
// any kind of exception.
// Attempt to switch to the exception page. However, this may itself fail
// for a number of reasons, in which case a ServletException is thrown.
output.reset();
if (LOG.isDebugEnabled())
LOG.debug("Uncaught exception", ex);
activateExceptionPage(cycle, output, ex);
}
finally
{
if (service != null)
monitor.serviceEnd(service.getName());
try
{
cycle.cleanup();
// Closing the buffered output closes the underlying stream as well.
if (output != null)
output.forceFlush();