Configuration for Tapestry portlet applications is quite similar to configuration of Tapestry servlet applications. In both cases, the WEB-INF/lib folder of the web application should include the Tapestry libraries and dependencies. For portlet applications, WEB-INB/lib should also include the tapestry-portlet- x.y .jar library.
The file WEB-INF/portlet.xml define the portlets packaged inside a web application. As with servlet Tapestry, we will use a framework-supplied Portlet class:
<portlet-app version="1.0" xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <description xml:lang="EN"></description> <portlet-name>myportlet</portlet-name> <display-name xml:lang="EN">My Tapestry Portlet</display-name> <portlet-class>org.apache.tapestry.portlet.ApplicationPortlet</portlet-class> <expiration-cache>-1</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> <portlet-mode>help</portlet-mode> <portlet-mode>edit</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>My Tapestry Portlet</title> <short-title>tapestry-portlet</short-title> <keywords></keywords> </portlet-info> </portlet> </portlet-app>
is always the class for Tapestry Portlets.
Tapestry applications can support any reasonable <mime-type>, though the available components make HTML and WML the most likely candidates.
Different portlet containers interpret the <portlet-mode> element differently. For example, assumes that every Portlet will support the "view" mode, and adding such an entry will result in a confusing duplication of the view icons on the Portlet's control tab. On the other hand, makes no assumptions, so you really should provide the "view" mode.
Later, we'll see how the combination of mime-type and portlet mode is used to select a Tapestry page.
Tapestry supports the other <portlet> elements, such as <portlet-preferences> and <user-attribute>.
Each Tapestry portlet application within a web application will construct its own Registry on initialization. The Registry will reflect all the libraries on the portlet's classpath (that is, including the Tapestry and HiveMind JARs in WEB-INF/lib). In addition, two optional module descriptors will be parsed and used, if present:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>app</display-name> <servlet> <servlet-name>ApplicationServlet</servlet-name> <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ApplicationServlet</servlet-name> <url-pattern>/app</url-pattern> </servlet-mapping> </web-app>
Some portals, such as , require additional configuration in the web.xml deployment descriptor.
Note that just one ApplicationServlet is needed, regardless of the number of Tapestry portlet applications within the WAR. This Tapestry servlet instance is primarily needed to support the use of the asset service, which is the mechanism by which private assets stored within the framework's JARs (such as images and stylesheets) can be provided to client web browsers.
In the above example, the default servlet mapping, to the /app URL, was used. You may use alternate mappings, but additional configuration is needed.
Tapestry has to bridge between the operation-centric organization of Portlets, and the page/component-centric organization of Tapestry itself. This is most visible when the a Tapestry Portlet first starts up, or when a user changes the window state or portlet mode by using the portlet's toolbar (to be specific: the toolbar provided by the Portal page).
In all these cases, a request is recieved by the Tapestry ApplicationPortlet that includes no real information in the request, just an indication of the desired window state and portlet mode.
Tapestry uses a set of rules to determine what to do in these cases. Each rule identifies up-to three factors used to select a page. These factors are mime-type, portlet-mode, and window-state.
The rules are sorted and consulted in order. The first match defines the page to activate and render. Omitting a factor means that the factor is not used when checking a rule against an incoming request.
The rules are defined by the configuration point
. Contributions to this configuration point consist of <match> elements:
<match [portlet-mode="..."] [mime-type="..."] [window-state="..."] page="..."/>
The default rules are:
<match portlet-mode="edit" page="Edit"/> <match portlet-mode="help" page="Help"/>
Any rules you define will be mixed in with these two default rules.
So, by contributing additional <match> rules to this configuration point, it is possible to precisely control which page should be rendered for each request; for example, you could have different pages for the "edit" portlet-mode, depending on whether the window state was normal or maximized:
<contribution configuration-id="tapestry.portlet.resolver.PageResolverRules"> <match portlet-mode="edit" window-state="maximized" page="EditLarge"/> </contribution>
Here, the Edit page would be used (as per the default rules) unless the window state was maximized, in which case the EditLarge page would be used.
What happens when none of the rules match? In that case, the View page is activated and rendered. The View page, in portlet Tapestry, is the equivalent of the Home page, in servlet Tapestry.
For advanced developers
: the process for determing the page for a request is ultimately based on a
extensible chain of command. The
configuration point defines the commands in the chain; by providing services
that implement the
interfaces, you can add even more sophisticated and precise control over the
mapping between requests and pages.