CVS: Tapestry/doc/src/UsersGuide configuration.xml,NONE,1.1.2.1 TapestryUsersGuide.xml,NONE,1.1.2.1 state.xml,NONE,1.1.2.1 spec.xml,NONE,1.1.2.1 .cvsignore,NONE,1.1.2.1 build.xml,NONE,1.1.2.1 script-spec.xml,NONE,1.1.2.1 intro.xml,NONE,1.1.2.1

Howard Lewis Ship <[email protected]>
Newsgroups gmane.comp.java.tapestry.cvs
Message-ID <[email protected]>
Update of /cvsroot/tapestry/Tapestry/doc/src/UsersGuide
In directory sc8-pr-cvs1:/tmp/cvs-serv15466/doc/src/UsersGuide

Added Files:
      Tag: hship-2-3
	configuration.xml TapestryUsersGuide.xml state.xml spec.xml 
	.cvsignore build.xml script-spec.xml intro.xml 
Log Message:
Start work on a new Tapestry User's Guide.

--- NEW FILE: configuration.xml ---
<!-- $Id: configuration.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->

<chapter id="configuration">
	<title>Configuring Tapestry</title>
	
<section id="configuration.deployment-descriptor">
	<title>Web Deployment Descriptor</title>
	
<para>
.... what goes into the web.xml ...
</para>
	
</section>  <!-- configuration.deployment-descriptor -->

<section id="configuration.search-path">
	<title>Configuration Search Path</title>
	
<para>
Tapestry occasionally must obtain a value for a configuration property.    These configuration
properties are items that are frequently optional, and don't fit into any particular
specification.  Many are related to the runtime environment, such as ...
</para>

<para>
Tapestry
is very flexible about where values for such properties may be obtained.  In general,
the search path for properties is:
</para>

<itemizedlist>
	<listitem>
		<para>
		As a &spec.property; of the &spec.application; (in the application specification,
		if the application uses one).
		</para>
	</listitem>
	<listitem>
		<para>
		As an <sgmltag class="starttag">init-parameter</sgmltag>
		for the servlet, in the web application deployment descriptor.
		</para>
	</listitem>
	<listitem>
		<para>
		As an <sgmltag class="starttag">init-parameter</sgmltag>
		for the servlet context, also in the web application deployment descriptor.
		</para>
	</listitem>
	<listitem>
		<para>
		As a JVM system property.
		</para>
	</listitem>
</itemizedlist>

<para>
It is expected that some configurations are not defined at any level; those will
return null.
</para>


<para>
Applications are free to leverage this lookup mechanism as well.  &IEngine; defines
a <varname>propertySource</varname> property (of type &IPropertySource;)
that can be used to perform such lookups.
</para>

<para>
Applications may also want to change or augment
the default search path; this is accomplished by overriding
&AbstractEngine; method <function>createPropertySource()</function>.
</para>
		
	
</section>  <!-- configuration.search-path -->

</chapter>
--- NEW FILE: TapestryUsersGuide.xml ---
<?xml version="1.0" encoding="utf-8"?>
<!-- $Id: TapestryUsersGuide.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
  "http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
  <!-- Useful snippets -->
  
<!ENTITY % TapestryLinks SYSTEM "../common/TapestryLinks.xml">
  
%TapestryLinks;
  
<!-- Each chapter is in its own file -->
  
<!ENTITY chap-intro SYSTEM "intro.xml">
<!ENTITY chap-state SYSTEM "state.xml">
<!ENTITY chap-configuration SYSTEM "configuration.xml">
  
<!ENTITY appendix-spec SYSTEM "spec.xml"> 
<!ENTITY appendix-script-spec SYSTEM "script-spec.xml">

<!-- Application, page, library, component specification entities  -->

<!ENTITY spec.application '<link linkend="spec.application"><sgmltag class="starttag">application</sgmltag></link>'>
<!ENTITY spec.bean '<link linkend="spec.bean"><sgmltag class="starttag">bean</sgmltag></link>'>
<!ENTITY spec.binding '<link linkend="spec.binding"><sgmltag class="starttag">binding</sgmltag></link>'>
<!ENTITY spec.configure '<link linkend="spec.configure"><sgmltag class="starttag">configure</sgmltag></link>'>
<!ENTITY spec.component '<link linkend="spec.component"><sgmltag class="starttag">component</sgmltag></link>'>
<!ENTITY spec.component-alias '<link linkend="spec.component-alias"><sgmltag class="starttag">component-alias</sgmltag></link>'>
<!ENTITY spec.component-specification '<link linkend="spec.component-specification"><sgmltag class="starttag">component-specification</sgmltag></link>'>
<!ENTITY spec.context-asset '<link linkend="spec.context-asset"><sgmltag class="starttag">context-asset</sgmltag></link>'>
<!ENTITY spec.description '<link linkend="spec.description"><sgmltag class="starttag">description</sgmltag></link>'>
<!ENTITY spec.extension '<link linkend="spec.extension"><sgmltag class="starttag">extension</sgmltag></link>'>
<!ENTITY spec.external-asset '<link linkend="spec.external-asset"><sgmltag class="starttag">external-asset</sgmltag></link>'>
<!ENTITY spec.field-binding '<link linkend="spec.field-binding"><sgmltag class="starttag">field-binding</sgmltag></link>'>
<!ENTITY spec.inherited-binding '<link linkend="spec.inherited-binding"><sgmltag class="starttag">inherited-binding</sgmltag></link>'>
<!ENTITY spec.library '<link linkend="spec.library"><sgmltag class="starttag">library</sgmltag></link>'>
<!ENTITY spec.library-specification '<link linkend="spec.library-specification"><sgmltag class="starttag">library-specification</sgmltag></link>'>
<!ENTITY spec.page '<link linkend="spec.page"><sgmltag class="starttag">page</sgmltag></link>'>
<!ENTITY spec.page-specification '<link linkend="spec.page-specification"><sgmltag class="starttag">page-specification</sgmltag></link>'>
<!ENTITY spec.parameter '<link linkend="spec.parameter"><sgmltag class="starttag">parameter</sgmltag></link>'>
<!ENTITY spec.private-asset '<link linkend="spec.private-asset"><sgmltag class="starttag">private-asset</sgmltag></link>'>
<!ENTITY spec.property '<link linkend="spec.property"><sgmltag class="starttag">property</sgmltag></link>'>
<!ENTITY spec.reserved-parameter '<link linkend="spec.reserved-parameter"><sgmltag class="starttag">reserved-parameter</sgmltag></link>'>
<!ENTITY spec.service '<link linkend="spec.service"><sgmltag class="starttag">service</sgmltag></link>'>
<!ENTITY spec.set-property '<link linkend="spec.set-property"><sgmltag class="starttag">set-property</sgmltag></link>'>
<!ENTITY spec.set-string-property '<link linkend="spec.set-string-property"><sgmltag class="starttag">set-string-property</sgmltag></link>'>
<!ENTITY spec.static-binding '<link linkend="spec.static-binding"><sgmltag class="starttag">static-binding</sgmltag></link>'>
<!ENTITY spec.string-binding '<link linkend="spec.string-binding"><sgmltag class="starttag">string-binding</sgmltag></link>'>


<!-- Script specification entities -->

<!ENTITY script-spec.body '<link linkend="script-spec.body"><sgmltag class="starttag">body</sgmltag></link>'>
<!ENTITY script-spec.foreach '<link linkend="script-spec.foreach"><sgmltag class="starttag">foreach</sgmltag></link>'>
<!ENTITY script-spec.if '<link linkend="script-spec.if"><sgmltag class="starttag">if</sgmltag></link>'>
<!ENTITY script-spec.if-not '<link linkend="script-spec.if-not"><sgmltag class="starttag">if-not</sgmltag></link>'>
<!ENTITY script-spec.include-script '<link linkend="script-spec.include-script"><sgmltag class="starttag">include-script</sgmltag></link>'>
<!ENTITY script-spec.initialization '<link linkend="script-spec.initialization"><sgmltag class="starttag">initialization</sgmltag></link>'>
<!ENTITY script-spec.input-symbol '<link linkend="script-spec.input-symbol"><sgmltag class="starttag">input-symbol</sgmltag></link>'>
<!ENTITY script-spec.let '<link linkend="script-spec.let"><sgmltag class="starttag">let</sgmltag></link>'>
<!ENTITY script-spec.script '<link linkend="script-spec.script"><sgmltag class="starttag">script</sgmltag></link>'>
<!ENTITY script-spec.set '<link linkend="script-spec.set"><sgmltag class="starttag">set</sgmltag></link>'>

<!ENTITY script-spec.full-content '<replaceable>text</replaceable> | &script-spec.foreach; | &script-spec.if; | &script-spec.if-not;'>


]>
<!-- Conventions:

	Component ids are <varname>
	Java packages and class names are <classname>
	Tapestry component aliases are <classname>

	In-line code snippets use <function>
	Property paths and JavaBeans property names used <varname>
-->
<book>
  <title>Tapestry User's Guide</title>
  <bookinfo>
    <author>
      <firstname>Howard</firstname>
      <surname>Lewis Ship</surname>
    </author>
    <copyright>
      <year>2003</year>
      <holder>Howard M. Lewis Ship</holder>
    </copyright>
  </bookinfo>
      
  &chap-intro;
  
  &chap-state;
         
  &chap-configuration;
                 
  &appendix-spec;
   
  &appendix-script-spec;    
    
</book>

--- NEW FILE: state.xml ---
<!-- $Id: state.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->

<chapter id="state">
	<title>Managing Server-Side State</title>
	
<para>
Server-side state is any information that exists on the server, and persists between request cycles.
This can be anything from a single flag all the way up to a large database result set.  In a typical
application, server-side state is the identity of the user (once the user logs in) and, perhaps,
a few important domain objects (or, at the very least, primary keys for those objects).
</para>

<para>
In a typical servlet application, managing server-side state is 
entirely the application's responsibility.  The Servlet API provides just the &HttpSession;, which
acts like a &Map;, relating keys to arbitrary objects.  It is the application's responsibility
to obtain values from the session, and to update values into the session when they change.
</para>

<para>
Tapestry takes a different tack; it defines server-side state in terms of the Engine,
the Visit and persistant page properties.
</para>

<para>
The Engine is important because, ultimately, it is the lone object stored into the &HttpSession;.  Because it
is persistant, the Visit and all page properties are also persistant.
</para>

<section id="state.visit">
	<title>Visit Object</title>
	
<para>
The Visit object is an application-defined object that may be obtained from the engine (via the
<varname>visit</varname> property of the &IEngine; or &IPage;).  By convention, the class is usually named <classname>Visit</classname>, but it can be
any class whatsoever, even &Map;.
</para>

<para>
The following example demonstrates how a listener method
may access the visit object.
</para>

<example>
	<title>Accessing the Visit object</title>
<programlisting>
public void formSubmit(&IRequestCycle; cycle)
{
    Visit visit = (Visit)getPage().getVisit();
    
    visit.<emphasis>doSomething()</emphasis>;   
}
</programlisting>
</example>

<para>
The Visit object is instantiated lazily, the first time it is needed.  Method
<function>createVisit()</function> of &AbstractEngine; is responsible for this.
</para>

<para>
In most cases, the Visit is an ordinary JavaBean, and therefore, has a no-arguments
constructor.  In this case, the complete class name of the
Visit is specified as 
<link linkend="configuration.search-path">configuration property</link>
<literal>net.sf.tapestry.visit-class</literal>.
</para>

<para>
Typically, the Visit class is defined in the application specification.
</para>

<example>
	<title>Defining the Visit class</title>
<programlisting>
<![CDATA[
<application name="Tapestry Component Workbench" 
	engine-class="net.sf.tapestry.engine.SimpleEngine">
  <property name="net.sf.tapestry.visit-class">tutorial.workbench.Visit</property>

  ...
]]>
</programlisting>
</example>

<para>
In cases where the Visit object does not have a no-arguments contructor, or
has other special initialization requirements, the method
<function>createVisit()</function> of &AbstractEngine; can be overridden.
</para>

<para>
There is a crucial difference between accessing the visit via the 
<varname>visit</varname> property of &IPage; and the
<varname>visit</varname> property of &IEngine;.  In the former case, accessing the visit
via the page, the visit <emphasis>will</emphasis> be created if it does not already exist.
</para>

<para>
Accessing the visit via the &IEngine; is different, the visit will <emphasis>not</emphasis>
be created if it does not already exist.
</para>

<para>
Carefully crafted applications will take heed of this difference and try to avoid
creating the visit unnecessarilly.  It is not just the creation of this one object that is
to be avoided ... creating the visit will likely force the entire application
to go stateful (create an &HttpSession;), and applications are more efficient
while <link linkend="state.stateless">stateless</link>.
</para>

</section> <!-- state.visit -->

<section id="state.page-properties">
	<title>Pesistant Page Properties</title>
	
<para>
Servlets, and by extension, JavaServer Pages, are inherently stateless.  That is, they will be used
simultaneously by many threads and clients.  Because of this, they must not store (in instance variables)
any properties or values that are specified to any single client.
</para>

<para>
This creates a frustration for developers, because ordinary programming techniques must be avoided.
Instead, client-specific state and data must be stored in the &HttpSession; or as &HttpServletRequest; attributes.
This is an awkward and limiting way to handle both <emphasis>transient</emphasis> state (state that is only needed
during the actual processing of the request) and
<emphasis>persistant</emphasis> state (state that should be available during the processing of this
and subsequent requests).
</para>

<para>
Tapestry bypasses most of these issues by <emphasis>not</emphasis> sharing objects between threads and clients.
For the duration of a request, a page and all components within the page are reserved to the single request.
There is no chance of conflicts because only the single thread processing the request will have access
to the page.  At the end of the request cycle, the page is returned to a pristine state and returned to the shared pool,
ready for reuse by the same client, or by a different client.
</para>

<para>
In fact, even in a high-volume Tapestry application, there will rarely be more than a few instances of any
particular page in the page pool.
</para>

<para>
For this scheme to work it is important that at the end of the request cycle, the page must return
to its pristine state.  The prisitine state is equivalent to a freshly created instance of the page.  In other words, any
properties of the page that changed during the processing of the request must be returned to thier initial values.
</para>

<para>
The best way to do this is to implement the method <function>initialize()</function> on your page.  This method is invoked
once when the page is first created; it is invoked again at the end of each request cycle.  An empty implementation
of this method is provided by &AbstractPage;.
</para>

<example>
	<title>Use of <function>initialize()</function> method</title>
<programlisting>
public class MyPage extends &BasePage;
{
    private String _message;
    
    public String getMessage()
    {
        return _message;
    }
    
    public void setMessage(String message)
    {
        _message = message;
    }
    
    protected void initialize()
    {
        _message = null;
    }
}
</programlisting>
</example>


<para>
If your page has additional attributes, they should also be reset inside
the <function>initialize()</function> method.
</para>

<para>
Now that we've shown how Tapestry allows pages to have <emphasis>transient</emphasis> state, we'll
show how to handle <emphasis>persistant</emphasis> state.
</para>	

<para>
Tapestry separates the persistant state of a page from any instance.  In Tapestry, a page may have many properties
and may have many components, each with many properties but only a tiny number of all those
properties needs to persist between request cycles.
</para>

<para>
For a property to be persistant, all that's necessary is that the accessor method notify
the framework of changes.  Tapestry will record the changes (using an &IPageRecorder;)
and, in later request cycles, will restore the property
using using the recorded value as the page instance is taken out of the page pool.
</para>

<para>
This notification takes the form of an invocation of the method
<function>fireObservedChange()</function>.  This method is provided by &AbstractComponent;
and is overloaded for all the scalar types, and for &Object;.
</para>

<example>
<title>Persistant Page Property</title>
<programlisting>
public class MyPage extends &BasePage;
{
    private int _itemsPerPage;
    
    public int getItemsPerPage()
    {
        return _itemsPerPage;
    }
    
    public void setItemsPerPage(int itemsPerPage)
    {
        _itemsPerPage = itemsPerPage;
        
        fireObservedChange("itemsPerPage", itemsPerPage);
    }
    
    protected void initialize()
    {
        _itemsPerPage = 10;
    }
}
</programlisting>
</example>

<para>
This sets up a property, <varname>itemsPerPage</varname> with a default value of 10.  If
the value is changed (perhaps by a form or a listener method),
the changed value will "stick" with the user who changed it, for the duration of their
session.
</para>

<note id="state.page-properties.declarative">
<title>Coming in 2.4</title>
<para>
A feature planned for release 2.4, but not yet coded, is <emphasis>declarative properties</emphasis>.
This will allow the transient and persistant properties of a page (or component) to be
declared in the specification.  Tapestry will take care of everything else; this will likely
use some form of bytecode engineering; that is, Tapestry will create a subclass on the fly,
providing accessor methods, the <function>initialize()</function> method, possibly even
the instance variables themselves.
</para>
</note>
	
</section> <!-- state.page-properties -->

<section id="state.component-properties">
	<title>Persistant Component Properties</title>
	
<para>
Transient and persistent properties are not limited just to pages.  The can be implemented
by components as well, though this takes slightly more work.  The <function>fireObservedChange()</function>
method is available to components as well as pages, but the initialization is slightly more complicated.
</para>

<para>
Components do not have the equivalent of the <function>initialize()</function> method.  Instead,
they must register for an event notification to tell them when the page is being <emphasis>detached</emphasis>
from the engine (prior to be stored back into the page pool).  This event is generated by the page itself.
</para>

<para>
The Java interface &PageDetachListener; is the event listener interface for this purpose.  Implementing
the interface is only part of the job, registering with the page is also necessary, and there
are timing issues.  The registration can't take place in the constructor, because
a freshly instantiated component doesn't yet have its <varname>page</varname> property set.
</para>

<para>
Tapestry provides a method, <function>finishLoad()</function>, for just this purpose: late initialization.
</para>

<example>
	<title>Persistant Component Properties</title>
<programlisting>
public class MyComponent extends &BaseComponent; implements &PageDetachListener;
{
    private String _myProperty;
    
    public void setMyProperty(String myProperty)
    {
        _myProperty = myProperty;
        
        fireObservedChange("myProperty", myProperty);
    }
    
    public String getMyProperty()
    {
        return _myProperty;
    }
    
    protected void initialize()
    {
        _myProperty = "<emphasis>a default value</emphasis>";
    }
    
    protected void finishLoad()
    {
        initialize();
        
        getPage().addPageDetachListener(this);
    }
    
    public void pageDetached(PageEvent event)
    {
        initialize();
    }
}
</programlisting>
</example>
	
<note>
<title>Coming in 2.4</title>
<para>
Along with support for <link linkend="state.page-properties.declarative">declarative properties</link>,
2.4 <emphasis>may</emphasis> simplify registerring.  Components that implement the key page
listener interfaces (&PageDetachListener;, &PageRenderListener; or &PageCleanupListener;) will
be automatically registerred with the page.
</para>
</note>

</section> <!-- state.component-properties -->

<section id="state.stateless">
	<title>Stateless Applications</title>
	
<para>
In a Tapestry application, the framework acts as a buffer between the application code and
the Servlet API ... in particular, it manages how data is stored into the &HttpSession;.
In fact, the framework controls <emphasis>when</emphasis> the session is first created.
</para>

<para>
This is important and powerful, because an application that runs, even just initially, without
a session consumes less resources that a stateful application.  This is even more important
in a clustered environment with multiple servers; any data stored into the &HttpSession; will
have to be replicated to other servers in the cluster, which can be expensive in terms of resources.  Using
less resources means better throughput and more concurrent clients, always a good thing
in a web application.
</para>

<para>
Tapestry defers creation of the &HttpSession; until one of two things happens:  When
the visit is created, or when the first persistant page property is recorded.  At this point,
Tapestry will create the &HttpSession; and store the engine into it.
</para>

<para>
Earlier, we said that the &IEngine; instance is stored in the &HttpSession;, but this is not always the case.
Tapestry maintains a pool of &IEngine; instances that are used for stateless requests.  An instance
is checked out of the pool and used to process a single request, then checked back into the pool for
reuse in a later request, by the same or different client.
</para>


<para>
For the most part, your application will be unaware of when it is stateful or stateless; statefulness
just happens on its own.  Ideally, at least the first, or "Home" page, should be stateless (it should be
organized in such a way that the visit is not created, and no persistant state is stored).  This will help
speed the initial display of the application, since no processing time will be used in creating the session.
</para>	
	
</section> <!-- state.stateless -->

</chapter>
--- NEW FILE: spec.xml ---
<!-- $Id: spec.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->

<appendix id="spec">
	<title>Tapestry Specification DTDs</title>
	

<para>
This appendix describes the four types of specifications
used in Tapestry.
</para>
 
<table>
	<title>Tapestry Specifications</title>
	<tgroup cols="5">
<thead>
<row>
	<entry>Type</entry>
	<entry>File Extension</entry>
	<entry>Root Element</entry>
[...1614 lines suppressed...]
	<entry>string</entry>
	<entry>yes</entry>
	<entry/>
	<entry>The name of the parameter to bind.</entry>
</row>
<row>
	<entry>key</entry>
	<entry>string</entry>
	<entry>yes</entry>
	<entry/>
	<entry>The localized property key to retrieve.
	</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>
</section> <!-- spec.string-binding -->

</appendix>

--- NEW FILE: .cvsignore ---
html

--- NEW FILE: build.xml ---
<?xml version="1.0"?>

<!DOCTYPE project [
    <!ENTITY docbook-setup SYSTEM "file:../common/docbook-setup.xml">
]>

<project name="Tapestry User's Guide" default="install">

<property name="root.filename" value="TapestryUsersGuide"/>

&docbook-setup;
    

</project>



--- NEW FILE: script-spec.xml ---
<!-- $Id: script-spec.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->

<appendix id="script-spec">
	<title>Tapestry Script Specification DTD</title>
	
<para>
Tapestry Script Specifications are frequently used with the &Script;
component, to create dynamic JavaScript functions, typically for use
as event handlers for client-side logic.
</para>

<para>
The root element is &script-spec.script;.
</para>

<para>
A script specifcation is a kind of specialized template that
takes some number of input symbols and combines and manipulates
them to form output symbols, as well as
body and initialization.  Symbols may
be simple strings, but are also frequently objects or components.
</para>

<para>
Script specifications use an Ant-like syntax to insert dynamic values
into text blocks.  <literal>${<replaceable>OGNL expression</replaceable>}</literal>.
The expression is evaluated relative to a &Map; of symbols.
</para>

<section id="script-spec.body">
	<title><sgmltag class="starttag">body</sgmltag> element</title>
	
<para>
Appears in: &script-spec.script;
</para>

<para>
Specifies the main body of the JavaScript; this is where
JavaScript variables and methods are typically declared.
This body will be passed to the &Body; component for inclusion
in the page.
</para>
	
<figure>
	<title><sgmltag class="starttag">body</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>	
</section> <!-- script-spec.body -->


<section id="script-spec.foreach">
	<title><sgmltag class="starttag">foreach</sgmltag> element</title>
	
<para>
Appears in: <emphasis>many</emphasis>
</para>

<para>
An element that renders its body repeatedly, much like a &Foreach; component.
An expression supplies a collection or array of objects, and its body is
rendered for each element in the collection.
</para>

<figure>
	<title><sgmltag class="starttag">foreach</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
	<entry>key</entry>
	<entry>string</entry>
	<entry>yes</entry>
	<entry/>
	<entry>The symbol to be updated with each successive value.</entry>
</row>
<row>
  <entry>expression</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The OGNL expression which provides the source of elements.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	

<figure>
	<title><sgmltag class="starttag">foreach</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>


</section> <!-- script-spec.foreach -->


<section id="script-spec.if">
	<title><sgmltag class="starttag">if</sgmltag> element</title>
	

<para>
Appears in: <emphasis>many</emphasis>
</para>

<para>
Conditionally renders its body, if a supplied OGNL 	
expression is true.
</para>

<figure>
	<title><sgmltag class="starttag">if</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>expression</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The OGNL expression to be evaluated.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	

<figure>
	<title><sgmltag class="starttag">if</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>

</section> <!-- script-spec.if -->


<section id="script-spec.if-not">
	<title><sgmltag class="starttag">if-not</sgmltag> element</title>
	

<para>
Appears in: <emphasis>many</emphasis>
</para>

<para>
Conditionally renders its body, if a supplied OGNL 	
expression is false.
</para>

<figure>
	<title><sgmltag class="starttag">if-not</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>expression</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The OGNL expression to be evaluated.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	

<figure>
	<title><sgmltag class="starttag">if-not</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>
	
</section> <!-- script-spec.if-not -->


<section id="script-spec.include-script">
	<title><sgmltag class="starttag">include-script</sgmltag> element</title>
	
<para>
Appears in: &script-spec.script;
</para>

<para>
Used to include a static JavaScript library.  A library will only be included once, regardless of
how many different scripts reference it.  Such libraries are located on the classpath.
</para>

	
<figure>
	<title><sgmltag class="starttag">include-script</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>resource-path</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The location of the JavaScript library.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	
</section> <!-- script-spec.include-script -->


<section id="script-spec.initialization">
	<title><sgmltag class="starttag">initialization</sgmltag> element</title>
	
<para>
Appears in: &script-spec.script;
</para>

<para>
Defines initialization needed by the remainder of the script.  Such initialization
is placed inside a method invoked from the HTML <sgmltag class="starttag">body</sgmltag>
element's <literal>onload</literal> event handler ... that is, whatever is placed inside
this element will not be executed until the entire page is loaded.
</para>

	

<figure>
	<title><sgmltag class="starttag">initialization</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>

	
</section> <!-- script-spec.initialization -->



<section id="script-spec.input-symbol">
	<title><sgmltag class="starttag">input-symbol</sgmltag> element</title>
	
<para>
Appears in: &script-spec.script;
</para>

<para>
Defines an input symbol for the script.  Input symbols can be thought of as parameters to the script.
As the script executes, it uses the input symbols to create new output symbols, redefine input symbols
(not a recommended practice) and define the body and initialization.
</para>

<para>
This element allows the script to make input symbols required and to restrict their type.  Invalid input symbols
(missing when required, or not of the correct type) will result in runtime exceptions.
</para>

<figure>
	<title><sgmltag class="starttag">input-symbol</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>key</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The input symbol to be checked.</entry>
</row>
<row>
	<entry>class</entry>
	<entry>string</entry>
	<entry>no</entry>
	<entry/>
	<entry>If specified, this is the complete, qualified class name for the symbol.
	The provided symbol must be assignable to this class (be a subclass, or implement
	the specified class if the specified class is actually an interface).
	</entry>
</row>
<row>
	<entry>required</entry>
	<entry><literal>yes | no</literal></entry>
	<entry>no</entry>
	<entry><literal>no</literal></entry>
	<entry>If <literal>yes</literal>, then a non-null value must be specified for
	the symbol.
	</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	
	
</section> <!-- script-spec.input-symbol -->


<section id="script-spec.let">
	<title><sgmltag class="starttag">let</sgmltag> element</title>
	


<para>
Appears in: &script-spec.script;
</para>

<para>
Used to define (or redefine) a symbol.  The symbol's value is taken from
the body of element (with leading and trailing whitespace removed).
</para>

<figure>
	<title><sgmltag class="starttag">let</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>key</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The key of the symbol to define.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>	
	


<figure>
	<title><sgmltag class="starttag">let</sgmltag> Elements</title>
<literallayout>
  (&script-spec.full-content;) *
</literallayout>
</figure>
	
</section> <!-- script-spec.let -->


<section id="script-spec.script">
	<title><sgmltag class="starttag">script</sgmltag> element</title>
	
<para>
<emphasis>Root element</emphasis>
</para>

<para>
The root element of a Tapestry script specification.
</para>

<figure>
	<title><sgmltag class="starttag">script</sgmltag> Elements</title>
<literallayout>
  &script-spec.include-script; *, &script-spec.input-symbol; *,
  (&script-spec.let; | &script-spec.set;) *,
  &script-spec.body; ?, &script-spec.initialization; ?
</literallayout>
</figure>
	
</section> <!-- script-spec.script -->


<section id="script-spec.set">
	<title><sgmltag class="starttag">set</sgmltag> element</title>
	
<para>
Appears in: &script-spec.script;
</para>

<para>
A different way to define a new symbol, or redefine an existing one.  The new symbol
is defined using an OGNL expression.
</para>

	
<figure>
	<title><sgmltag class="starttag">set</sgmltag> Attributes</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
  <entry>Name</entry>
  <entry>Type</entry>
  <entry>Required ?</entry>
  <entry>Default Value</entry>
  <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
  <entry>key</entry>
  <entry>string</entry>
  <entry>yes</entry>
  <entry/>
  <entry>The key of the symbol to define.</entry>
</row>
<row>
	<entry>expression</entry>
	<entry>string</entry>
	<entry>yes</entry>
	<entry/>
	<entry>The OGNL expression to evaluate.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</figure>		
</section> <!-- script-spec.set -->

	
</appendix>

--- NEW FILE: intro.xml ---
<!-- $Id: intro.xml,v 1.1.2.1 2002/12/22 13:47:58 hship Exp $ -->

<chapter id="intro">
	<title>Introduction</title>
	
<para>
Tapestry is a component-based web application framework, written in Java.  Tapestry
is more than a simple templating system; Tapestry builds on the Java Servlet API to
build a platform for creating dynamic, interactive web sites.  More than
just another templating language, Tapestry is a real framework for building
complex applications from simple, reusable components.  Tapestry offloads
much of the error-prone work in creating web applications into the framework itself,
taking over mundane tasks such as dispatching incoming requests, constructing and
interpretting URLs encoded with information, handling localization and internationalization
and much  more besides.
</para>

<para>
The "mantra" of Tapestry is "objects, methods and properties".  That is, rather than have developers concerned
about the paraphanlia of the Servlet API: requests, responses, sessions, attributes, parameters, URLs and so on,
Tapestry focuses the developer on objects (including Tapestry pages and components, but
also including the domain objects  of the application), methods on those objects,
and JavaBeans properties of those objects.  That is, in a Tapestry application, the
actions of the user (clicking links and submitting forms) results in changes to object properties
combined with the invocation of user-supplied methods (containing application logic).  Tapestry
takes care of the plumbing necessary to connect these user actions 
with the objects.
</para>

<para>
This is not to say the Servlet API is inaccessible; it is simply not
<emphasis>relevant</emphasis> to a typical Tapestry user.
</para>

<para>
This document describes many of the internals of Tapestry.  It is not a tutorial,
that is available as a separate document.  Instead, this document is a guide to
some of the internals of Tapestry, and is intended for experienced developers
who wish to leverage Tapestry fully.
</para>

<para>
Tapestry is currently in release 2.4, and has come a long way in the last couple
of years.  Tapestry's focus is still on generating dynamic HTML pages.
</para>

<para>
Nearly all of Tapestry's API is described in terms of interfaces, with
default implementations supplied.
By substituting new objects with the correct interfaces, the behavior of the framework
can be changed significantly.  This allows for changes to where Tapestry specifications and templates
originate from, and how server-side state is persisted (for example).
</para>

<para>
Finally, Tapestry boasts extremely complete JavaDoc API documentation.  This document
exists to supplement that documentation, to fill in gaps that may not be obvious.  The JavaDoc
is often the best reference.
</para>

<section id="intro.pages-and-components">
	<title>Pages and Components</title>
	
<para>
Tapestry divides an application into a set of pages.  Each page is assembled from Tapestry components.
Components themselves may be assembled from other components ... there's no artificial depth limit.
</para>


<para>
Tapestry pages are themselves components, but are components with some special responsibilities.
</para>

<para>
All Tapestry components can be containers of other components.  Tapestry pages, and most
user-defined components, have a template, a special HTML file that defines the static
and dynamic portions of the component, with markers to indicate where embedded components are
active.  Components do not have to have a template, most of the components provided with
Tapestry generate their protion of response in code, not using a template.
</para>

<para>
Components may have one or more named parameters which may be set (or, "bound") by the page or component
which contains them.  Unlike Java method parameters, Tapestry component parameters may be
bidirectional; a component may read a parameter to obtain a value, or write a parameter
to set a value.
</para>

<para>
Most components are concerned only with generating HTML.  A certain subset of components deal with the flip-side
of requests; handling of incoming requests.  Link classes, such as &PageLink;, &DirectLink; and
&ActionLink;, create clickable links in the rendered page and are involved in dispatching to user-supplied
code when such a link is triggered by clicking it.
</para>

<para>
Other components, &Form;, and the form element components (&TextField;, &PropertySelection;, &Checkbox;, etc.),
facillitate HTML forms.  When such components render, they read properties from application objects so as
to provide default values.  When forms are submitted, the components
within the form read HTTP query parameters, convert the values to appropriate types
and then update properties of application objects.
</para> 

</section> <!-- intro.pages-and-components -->

<section id="intro.engine-service-visit">
	<title>Engines, Services and the Visit</title>
	
<para>
Tapestry has evolved its own jargon over time.
</para>

<para>
The Engine is a central object, it occupies the same semantic space in Tapestry that the
&HttpSession; does in the Servlet API.  The Engine is ultimately responsible for
storing the persistant state of the application (properties that exist from one request to
the next), and this is accomplished by storing the Engine into the &HttpSession;.
This document will largely discuss the <emphasis>default</emphasis> implementation,
with notes about how the default implementation may be extended or overriden, where appropriate.
</para>
	
<para>
Engine services are the bridge between servlets and URLs and the rest of Tapestry.  Engine services 
are responsible	for encoding URLs, providing query parameters that identify, to the framework,
the exact operation that should occur when the generated URL is triggered (by the end user
clicking a link or submitting a form).  Services are also responsible for dispatching
those incoming requests.  This encapsulation of URL encoding and decoding inside a single class
is key to how Tapestry components can flexibily operate without concern for how they are contained and on which
page ... the services take into account page and location when formulating URLs.
</para>

<para>
The <link linkend="state.visit">Visit</link> is not a particular object, 
it is an application-defined object that acts as a focal point
for all server-side state (not associated with any single page).  Individual applications define for themselves
the class of the Visit object.  The Visit is stored as a property of the Engine, and so is ultimately
stored persistantly in the &HttpSession;
</para>
	
</section> <!-- intro.engine-service-visit -->

</chapter>


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.