paulb@654 | 1 | <?xml version="1.0" encoding="iso-8859-1"?> |
paulb@527 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
paulb@527 | 3 | <html xmlns="http://www.w3.org/1999/xhtml"><head> |
paulb@527 | 4 | <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" /> |
paulb@654 | 5 | <title>Transaction Attributes</title> |
paulb@527 | 6 | <link href="styles.css" rel="stylesheet" type="text/css" /></head> |
paulb@527 | 7 | <body> |
paulb@527 | 8 | <h1>Transaction Attributes</h1> |
paulb@527 | 9 | <p>Sometimes, an application will process an incoming request using a number of different resource objects. For example, in the <a href="paths-filesystem.html">"Treating the Path Like a Filesystem"</a> document, an example is given which involves a number of <code>MapResource</code> |
paulb@527 | 10 | objects arranged in a hierarchy, and whilst such objects are used |
paulb@527 | 11 | merely to select other resources which are then used to provide some |
paulb@527 | 12 | kind of output, there may be other situations where such objects may |
paulb@527 | 13 | need to record some information about their activities, so that the |
paulb@527 | 14 | output-producing resource may customise the output accordingly.</p><p>In the example mentioned above, let |
paulb@527 | 15 | us consider the effect of replacing the special mapping from explicitly |
paulb@527 | 16 | specified year numbers with a new resource object that recognises |
paulb@527 | 17 | year numbers and dispatches requests to other resources:</p><pre>news_resource = YearResource({"document.html" : document_resource, "article.html" : article_resource})<br />documents_resource = MapResource({"news" : news_resource})<br />top_resource = MapResource({"documents" : documents_resource})</pre><p>What <code>YearResource</code> objects would do is to take the year number from the URL (see <a href="paths.html">"URLs and Paths"</a>) |
paulb@527 | 18 | and then to match a name in the dictionary it was initialised with, in |
paulb@527 | 19 | order to dispatch the transaction to a suitable resource. However, it |
paulb@527 | 20 | is likely that the year number is important to such resources: we would |
paulb@527 | 21 | expect to see a different Web page for <code>document.html</code> in <code>2005</code> than in <code>2004</code>, for example. Consequently, the <code>YearResource</code> needs a way to communicate such information to other resources.</p><p>Although we could provide special methods or change the parameters of the <code>respond</code> method in the <code>document_resource</code> and <code>article_resource</code> |
paulb@527 | 22 | objects in order to create a "channel" through which year information |
paulb@527 | 23 | could be passed, an alternative is to retain the existing interface and |
paulb@527 | 24 | behaviour of those objects and to store such information in the |
paulb@527 | 25 | transaction object itself. Since the transaction is essential in |
paulb@527 | 26 | the processing of any incoming request, we can be certain that it will |
paulb@527 | 27 | be available to store and to provide such information when necessary. </p><h2>Using Transaction Attributes</h2> |
paulb@527 | 28 | <p>We may obtain the attributes from the transaction by performing a method call as follows:</p><pre> # In the respond method...<br /> attributes = trans.get_attributes()</pre><p>This |
paulb@527 | 29 | will provide a dictionary mapping names to attribute values. The |
paulb@527 | 30 | structure of the values is not strictly defined, and it is the |
paulb@527 | 31 | application's role to enforce its own rules on the data stored in the |
paulb@527 | 32 | attributes dictionary.</p><p>Setting and getting values is as straightforward as using a normal dictionary:</p> |
paulb@527 | 33 | <pre> # Continuing from above...<br /> attributes["year"] = year<br /> # Later...<br /> if attributes.has_key("year"):<br /> year = attributes["year"]<br /></pre><p>As described in the <a href="../apidocs/public/WebStack.Generic.Transaction-class.html#get_attributes">API documentation</a>, |
paulb@527 | 34 | the attributes dictionary exists as long as the transaction object |
paulb@527 | 35 | itself. Should information need to be stored beyond the lifetime of a |
paulb@527 | 36 | transaction, the appropriate persistent information facilities should |
paulb@613 | 37 | be used instead - see <a href="sessions.html">"Sessions and Persistent Information"</a> for more details.</p><h2>Storing the Application Location in an Attribute</h2><p>One |
paulb@613 | 38 | use of attributes is to take the location of an application, defined in |
paulb@613 | 39 | terms of its path, and to store that information in an attribute. Such |
paulb@613 | 40 | information would then travel to different resources in an application |
paulb@613 | 41 | as part of the transaction, enabling those resources to generate things |
paulb@613 | 42 | like hyperlinks which contain "absolute" rather than "relative" |
paulb@613 | 43 | references to various parts of the application. Consider an application |
paulb@613 | 44 | deployed at the following URL:</p><pre>http://application.business.com/bizapp/</pre><p>Inside this application, we may have other URLs which expose certain functions:</p><pre>http://application.business.com/bizapp/services/finance/accounting<br />http://application.business.com/bizapp/services/customer/invoice</pre><p>It |
paulb@613 | 45 | may be interesting for these functions to know the location of the |
paulb@613 | 46 | top-level or root of the application in order to, for example, generate |
paulb@613 | 47 | hyperlinks to the top-level or to other established functions. Thus, we |
paulb@613 | 48 | may decide to remember the top-level path which would be the following:</p><pre>/bizapp/</pre><p>Now, normally the <code>get_path_without_info</code> method will provide this information, but what if we wanted to remember the following path instead...?</p><pre>/bizapp/services/</pre><p>In |
paulb@613 | 49 | fact, we can make use of the other path-related methods to obtain this |
paulb@613 | 50 | path, provided that we ask for this information at the correct point in |
paulb@613 | 51 | processing the request. Let us imagine that we have used the <a href="resource-map.html"><code>MapResource</code></a> class to build up the path hierarchy:</p><pre>resource = MapResource({<br /> "services" : MapResource({<br /> "finance" : finance_department,<br /> "customer" : customer_department<br /> })<br /> })</pre><p>We |
paulb@613 | 52 | would want to define a resource to process the request and |
paulb@613 | 53 | remember the path details just before choosing between the finance and |
paulb@613 | 54 | customer departments. This resource would do the following:</p><ol><li>Ask for the path without info, along with the processed virtual path info (as described in <a href="path-info.html">"Paths To and Within Applications"</a>).</li><li>Join the paths together.</li><li>Store the result on an attribute (called "root", perhaps).</li><li>Invoke another resource.</li></ol><p>The advantage of doing this dynamically is that should we decide to change the location of the application or the path to <code>services</code> within it, we will not need to track down hard-coded path values and change them in lots of different places.</p><p>Fortunately, WebStack provides a class to do this work for us - <code>PathSelector</code> - and we can use it in the following way:</p><pre>from WebStack.Resources.Selectors import PathSelector<br /><br />resource = MapResource({<br /> "services" : PathSelector(<br /> MapResource({<br /> "finance" : finance_department,<br /> "customer" : customer_department<br /> })<br /> )<br /> })</pre><p>Now, once the <code>services</code> part of the path has been detected, the <code>PathSelector</code> resource will discover the path details, store them on an attribute, and then invoke the <code>MapResource</code> which chooses between departments, which in turn invokes other resources, and so on. However, all of the resources "below" the <code>PathSelector</code> resource |
paulb@613 | 55 | will have an attribute called "root" which contains the selected "root |
paulb@613 | 56 | path" of the application (or at least the interesting part of the |
paulb@654 | 57 | application).</p><p>See the <a href="selectors.html">"Selectors"</a> document for more details of the <code>PathSelector</code> class.</p></body></html> |