| <!-- $Id$ --> |
| <!-- |
| Copyright 2004 The Apache Software Foundation |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <chapter id="coding"> |
| <title>Coding Tapestry Applications</title> |
| <para> |
| After performing the design steps from the previous chapter, it |
| is time to start coding. The designs will imply |
| certain requirements for the implementations. |
| </para> |
| <section id="coding.engine"> |
| <title>Application Engine</title> |
| <para> |
| Application engines will be serialized and de-serialized as part of |
| load balancing and fail over. As much as possible, attributes of the application |
| object should be transient. For example, the instance variable that |
| holds the <classname>ApplicationSpecification</classname> is transient; if |
| needed (after de-serialization), the engine can locate the specification from |
| its servlet (the servlet reads the application specification once, when it is first initialized). |
| </para> |
| <para> |
| This is largely not an issue, since most applications use a provided class, |
| such as &SimpleEngine;. Subclassing |
| is only necessary when the application needs a different method of instantiating the visit object, or |
| needs to store additional data (see <link linkend="coding.stateless" endterm="coding.stateless.title"/>). |
| In some cases, it is convienient to create a subclass to provide common component listener methods. |
| </para> |
| </section> |
| <section id="coding.visit"> |
| <title>Visit Object</title> |
| <para> |
| The visit object will contain all the data about a client's |
| visit to the web application. If possible, it should have a no-arguments |
| constructor (this allows &SimpleEngine; to instantiate it as needed). |
| </para> |
| <para> |
| Keeping the size of the serialized engine small is a |
| good goal for overall performance and scalability, and the visit object is serialized |
| with the engine. During initial development, the visit |
| object should implement the <classname>java.io.Serializable</classname> interface. |
| </para> |
| <para> |
| Once the application, and the structure of the visit object, is |
| stable, the more efficient <classname>java.io.Externalizable</classname> interface should be implemented instead. |
| </para> |
| <para> |
| In addition, deferring the creation of the visit object as late as |
| possible is also of benefit, since this is the best way to keep the serialized engine small. |
| </para> |
| </section> |
| <section id="coding.stateless"> |
| <title id="coding.stateless.title">Operating Stateless</title> |
| <para> |
| Tapestry applications can operate in a stateless mode, that is, without a &HttpSession;. The |
| framework automatically creates a session when needed; when the Visit object is first created, |
| or when any persistent page properties are changed. |
| </para> |
| <para> |
| Ideally, the <classname>Home</classname> page of the application should not trigger the creation of a session: |
| it should be careful not to create the Visit object. Remember that hits on your application will form |
| a curve: The <classname>Home</classname> page is at the top of the curve, and it drops of rapidly as |
| users penetrate deeper into the application ... how many times have you visited the front page of a web site |
| and gone no further? |
| </para> |
| <para> |
| Stateless operations will affect &ActionLink;, &DirectLink; and &Form; components on your pages. By default, they |
| will reject requests while the application is running stateless; the user will be redirected |
| to the <classname>StaleSession</classname> page. This is appropriate, since normally, the lack of a session |
| means that the previous session timed out and was discarded. |
| </para> |
| <para> |
| Each of these components has a <varname>stateful</varname> parameter which may be bound to |
| <literal>false</literal>. When <varname>stateful</varname> is false, the components will accept stateless |
| requests. |
| </para> |
| <para> |
| As the developer, you must keep a careful eye on what's stateful vs. stateless, and look to move |
| stateless data into the engine, so as to avoid creating a visit object as long as possible. For example, |
| the engine can resolve and store |
| EJB home interfaces and references to <emphasis>stateless</emphasis> session EJBs. |
| Even read-only database data can be stored in the engine. However, anything that is related to a particular |
| user must be stored in the visit object (or a persistent page property). |
| </para> |
| <para> |
| It is also important to not accidentally create the visit object. Every page includes |
| a <varname>visit</varname> property which will create the visit if it doesn't already exist. This will, |
| in turn, force the creation of an &HttpSession;. On the other hand, the property path |
| <varname>engine.visit</varname> will <emphasis>not</emphasis> create the visit object. |
| To avoid creating the visit, you may need to wrap some of your HTML template inside |
| a &Conditional; component whose condition parameter is bound to the property <varname>engine.visit</varname>. |
| </para> |
| </section> |
| <section id="coding.ejb"> |
| <title>Enterprise JavaBeans Support</title> |
| <para> |
| The visit object should provide access to the most commonly |
| used Enterprise JavaBeans used in the application. It can provide a central location |
| for the common code (related to JNDI and to narrowing EJB references), rather |
| than have that scattered throughout the application. |
| </para> |
| <para> |
| It is important to remember that EJB references are not serializable. |
| However, it is possible to convert between an EJB reference and an EJB handle, |
| and handles are serializable. The visit should make any |
| instance variables that store EJB references transient, and should perform |
| extra serialization work to serialize and restore the necessary EJB handles. |
| </para> |
| <para> |
| Also remember that persistent page properties that are EJB references are |
| <emphasis>automatically</emphasis> |
| converted to handles when stored, and back into references when restored. |
| </para> |
| </section> |
| <section id="coding.page-classes"> |
| <title>Page classes</title> |
| <para> |
| It is often useful to create one or two subclasses of |
| &BasePage; specific to your application. |
| Often your application will have a consistent navigational border on some |
| or all pages that can be supported by the base class. |
| Many applications have one set of pages that are visible |
| to unidentified guests, and a second section that is visible once the user logs |
| in. A base class for the second set of pages could override the |
| <function>validate()</function> method to redirect to a login page |
| if the user is not already logged in. |
| </para> |
| </section> |
| </chapter> |