Struts in Action: Developing Applications with Tiles, Page 5
11.4 Tile attributes
Being able to extend Definitions and overload attributes is a very powerful feature. But so far, we've only shown examples where the attributes are static values hardcoded into the pages. What if you would like to specify an attribute at runtime? Shouldn't an Action be able to pass the value of an attribute to a tile?
Yes, it can. The secret is that Tiles stores the attributes in its own context. Just as JSP stores attributes in a page context, Tiles stores its attributes in a Tiles context associated with the user's request.
There is nothing mysterious about the Tiles context. It is simply a collection that Tiles creates in the request for the use of its components. Specialized contexts are a popular technique for managing the various objects components create and then share with others, especially when control may pass from one application layer to another. Several of the Tiles tags are designed to be used with the Tiles context, including useAttribute.
The <tiles:useAttribute> tag makes one of the Tiles context attributes available through the page context. This makes the attribute available to other tags that read the page context, like the Struts <bean:write> tag.
The same attribute name can be used in either context
<tiles:useAttribute name="myAttribute" />
or another name can be specified:
<tiles:useAttribute attributeName="anAttribute" name="myAttribute" />
Once Tiles has put the attribute into page scope, the Struts bean tag can refer to the message in the usual way:
<bean:write name="myAttribute" />
The <useAttribute> tag can also be used to declare a scripting variable for use in a JSP scriptlet:
<tiles:useAttribute id="list" name="myAttribute" classname="java.util.List" />
In general, the <useAttribute> tag corresponds to the <useBean> action and the Struts <bean:define> tag but allows access to the attributes in the Tiles context.
Note that each tile is an individual JSP and therefore has its own page context. To export an attribute so that it is available to other tiles that may make up the completed response page, specify another scope. For example,
<tiles:useAttribute name="myAttribute" scope="request"/>
puts the attribute in request scope where a tag in another tile would be able to find it.
Since each tile is technically a different "page," each is in its own page scope. If you want to avoid conflicts with attributes on another tile, you can use page scope. If you want an attribute to be shared with another tile, you can use request scope instead.
The <useAttribute> operations are rendered sequentially. A tile rendering further down the page would be able to use the attribute, but one rendering earlier would not be able to find it (since it doesn't exist yet).
By default, the <tiles:importAttribute> tag imports all of the Tiles context attributes into the page context:
Any and all attributes stored in the current Tiles context would now be available through the standard page context.
Optionally, a single attribute or another context may be specified:
<tiles:importAttribute name="myAttribute" scope="request"/>
But, unlike <useAttribute>, <importAttribute> does not support renaming attributes or exposing them as scripting variables.
The <tiles:put> tag is used to associate a value to an attribute. The name property will usually be specified as a simple string, but the value may be specified in a variety of ways: as a tag property, as a tag body, and as a JavaBean.
put as tag property
When used in a JSP, this is the most common form of the put command. The value is usually set using a simple string but can also be a runtime value:
<tiles:put name="title" value="My first page" />
<tiles:put name="title" value="<%=myObject%>" />
put as tag body
As is the case with many JSP tags, the value property can also be set as the tag's body:
<tiles:put name="title">My first page</tiles:put>
This approach can also be used to nest the output of other JSP tags:
<tiles:put name="title"><bean:write message="first.pageTitle"/> </tiles:put>
put as a bean defined in some scope
Like many of the Struts tags, the attribute can be passed via a bean:
<tiles:put name="title" beanName="myBean" />
The object identified by beanName is retrieved, and its value used as the attribute value. If myBean is not a String, the Struts or Tiles JSP tags will automatically call the object's default toString() method so that the result of myBean.toString() will be used to set the value property.
By default, the scopes will be searched in the usual order, until the first instance of myBean is found. You may also specify a particular scope:
<tiles:put name="title" beanName="myBean" beanScope="session"/>
This would ignore any instance of myBean in the page or request scope and check the session instead. Tiles adds a context of its own, called tiles, that is checked after the standard scopes. The values accepted by beanScope are page, request, application, and tiles.
put as a property of a bean defined in some scope
Again like many of the Struts tags, you can also specify a certain property on a JavaBean. The
<tiles:put name="title" beanName="myBean" beanProperty="myProperty"/>
This would call the equivalent of myBean.getMyProperty() to set the value of the title attribute.
Specifying the attribute type
The <put> tag is used to set an attribute that will be used by another tag, usually either <tiles:insert> or <tiles:get>. The corresponding tag may use the value passed in various ways. It may represent a direct string, a page URL, or another Definition to insert. The type of data the attribute is meant to represent can be specified in the put tag with the optional type property. This can help the corresponding tag insert the value as intended:
<tiles:put name="footer" value="/tiles/footer.jsp" type="page"/>
The type, when specified, can be any one of the tokens: string, page, or definition. Table 11.2 provides a description of each of the tokens.
|Table 11.2 Valid tokens for the type property of the put tag|
|string||The value property denotes a String.|
|page||The value property denotes a URL.|
|definition||The value property denotes a Definition name.|
Specifying the security role
When container-based authentication is being used, you can also specify the role for a tile. If the user is not in the specified role, then the attribute value is not set. This allows you to specify a tile for each security role and let the framework select the appropriate one for the current user:
<tiles:put name="title" value="myValue" role="myManager"/><tiles:put name="title" value="myValue" role="myStaff"/>
If <put> is being used in a <tiles:insert> tag, the role is checked immediately. If <put> is being used within a <tiles:definition> tag, the role is checked when the Tiles context is initialized.
11.4.4 putList and add
In addition to accepting single objects, Tiles attributes can be of type java.util.List. You can specify a series of objects for an attribute and pass them as a single attribute. The <tiles:add> tag is nested within <tiles:putList> to specify the items to be placed on the list:
<tiles:insert page="menu.jsp" > <tiles:putList name="items"> <tiles:add value="home" /> <tiles:add value="documentation"/> </tiles:putList></tiles:insert>
The <putListgt; tag is often used with the <useAttributegt; or <importAttributegt; tag to make the list accessible to other tags on the page:
<tiles:importAttribute/><TABLE><logic:iterate id="item" name="items" ><TR> <TD> <bean:write name="item"> </TD></TR></logic:iterate></TABLE>