Handling A Bad Context

With each page you design it's important to decide how to handle a bad activation context, because a bad context can occur in various ways.

For example, look at the URL of this page. The activation context is clearly visible as 1 and it is easy to change. Try replacing it with 2 and you will see person 2. Users may become accustomed to this facility.

Here is the requested person:

Id
1
Version
76
First Name
Acme2
Last Name
456
Region
East Coast
Start Date
Jun 19, 1952

In this example a bad context could occur several ways:

Here are the alternatives:

  1. Handle it on the same page - either display the person or display the error.
    This approach has the big advantage that it keeps the same URL - the user can see what they requested.
    The "exception" event can help simplify this. See References below.
  2. Return a new page, possibly passing it the exception or a message to display.
    The page could even return HTTP 404 as described here.
  3. Throw an exception and let Tapestry's exception reporting page catch it.
    This is the simplest approach but probably not suitable for production. See the Exception Reporting Page example.
  4. Throw an exception and catch it with your own exception reporting page as described in the Exception Reporting Page example.
    The exception reporting page could give certain exceptions special treatment eg. you might like to treat expected exceptions, like DoesNotExistException and NotAuthorisedException, differently than unexpected exceptions.

This page has been built to handle only one situation: person does not exist. All other problems will be caught by the exception reporting page.

EventContext
To handle a variable number of context parameters, or even an unexpected number of context parameters, use EventContext. See the Variable Parameters example, Easy Object Select example, and One Page CRUD example.

References: Intercepting Event Exceptions, Overriding Exception Reporting, EventContext. If, BeanDisplay.

Home

The source for Person, @EJB handling, etc. is shown in the @EJB example.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body class="container">

    <h3>Handling A Bad Context</h3>

    <p>With each page you design it's important to decide how to handle a bad activation context, because a bad context
        can occur in various ways.</p>

    <p>
        For example, look at the URL of this page. The activation context is clearly visible as <em>1</em> and it is easy to
        change. Try replacing it with <em>2</em> and you will see person 2. Users may become accustomed to this facility.
    </p>

    <p>Here is the requested person:</p>

    <div class="eg">
        <t:if test="person">
            <t:beandisplay object="person" />
        </t:if>
        <t:if test="!person">
            <div class="alert alert-danger">Person ${personId} does not exist.</div>
        </t:if>
    </div>

    <p>In this example a bad context could occur several ways:</p>
    <ul>
        <li>You've removed the context from the URL.</li>
        <li>
            You've chosen a person that does not exist, eg. <em>100</em>.
        </li>
        <li>You are not authorised to the person (in JumpStart this is not checked).</li>
        <li>
            The format of the context is incorrect, eg. <em>abc</em>.
        </li>
        <li>You bookmark the page but when you return to it later the context is no longer valid because data,
            authorization, or the application have changed.</li>
    </ul>

    <p>Here are the alternatives:</p>
    <ol>
        <li>
            <strong>Handle it on the same page</strong> - either display the person or display the error.<br /> This approach has
            the big advantage that it keeps the same URL - the user can see what they requested.<br /> The <em>"exception"</em>
            event can help simplify this. See References below.
        </li>
        <li>
            <strong>Return a new page</strong>, possibly passing it the exception or a message to display.<br /> The page could
            even return <a href="http://en.wikipedia.org/wiki/404_error">HTTP 404</a> as described <a
                href="http://news.gmane.org/find-root.php?message_id=%3c48A4290A.7010407%40fsadev.com%3e">here</a>.
        </li>
        <li>
            Throw an exception and let <strong>Tapestry's exception reporting page</strong> catch it. <br /> This is the simplest
            approach but probably not suitable for production. See the Exception Reporting Page example.
        </li>
        <li>
            Throw an exception and catch it with <strong>your own exception reporting page</strong> as described in the Exception
            Reporting Page example.<br /> The exception reporting page could give certain exceptions special treatment eg.
            you might like to treat expected exceptions, like DoesNotExistException and NotAuthorisedException, differently 
            than unexpected exceptions.
        </li>
    </ol>

    <p>This page has been built to handle only one situation: person does not exist. All other problems will be caught
        by the exception reporting page.</p>

    <p>
        <strong>EventContext</strong><br /> To handle a variable number of context parameters, or even an unexpected number of
        context parameters, use <a href="http://tapestry.apache.org/component-events.html#ComponentEvents-EventContext">EventContext</a>.
        See the Variable Parameters example, Easy Object Select example, and One Page CRUD example.
    </p>

    References:
    <a href="http://tapestry.apache.org/component-events.html#ComponentEvents-InterceptingEventExceptions">Intercepting
        Event Exceptions</a>,
    <a href="http://tapestry.apache.org/overriding-exception-reporting.html">Overriding Exception Reporting</a>,
    <a href="http://tapestry.apache.org/component-events.html#ComponentEvents-EventContext">EventContext</a>.
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/If.html">If</a>,
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/BeanDisplay.html">BeanDisplay</a>.
    <br />
    <br />

    <p>
        <t:pagelink page="Index">Home</t:pagelink>
    </p>

    <p>The source for Person, @EJB handling, etc. is shown in the @EJB example.</p>

    <t:tabgroup>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/infrastructure/HandlingABadContext.tml" />
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/infrastructure/HandlingABadContext.java" />
        <t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/plain.css" />
    </t:tabgroup>
</body>
</html>


package jumpstart.web.pages.examples.infrastructure;

import javax.ejb.EJB;

import jumpstart.business.domain.person.Person;
import jumpstart.business.domain.person.iface.IPersonFinderServiceLocal;

import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;

@Import(stylesheet = "css/examples/plain.css")
public class HandlingABadContext {

    // The activation context

    @Property
    private Long personId;

    // Screen fields

    @Property
    private Person person;

    // Generally useful bits and pieces

    @EJB
    private IPersonFinderServiceLocal personFinderService;

    // The code

    void onActivate(Long personId) {
        this.personId = personId;
    }

    Long onPassivate() {
        return personId;
    }

    void setupRender() {
        // Get person - ask business service to find it (from the database)
        person = personFinderService.findPerson(personId);
        // Handle null person in the template (with an If component).
    }
}


.eg {
                margin: 20px 0;
                padding: 14px;
                border: 1px solid #ddd;
                border-radius: 6px;
                -webkit-border-radius: 6px;
                -mox-border-radius: 6px;
}