paulb@354 | 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
paulb@354 | 2 | <html xmlns="http://www.w3.org/1999/xhtml"> |
paulb@354 | 3 | <head> |
paulb@354 | 4 | <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" /> |
paulb@354 | 5 | <title>Integrating with Other Systems</title> |
paulb@354 | 6 | <meta name="generator" |
paulb@354 | 7 | content="amaya 8.1a, see http://www.w3.org/Amaya/" /> |
paulb@354 | 8 | <link href="styles.css" rel="stylesheet" type="text/css" /> |
paulb@354 | 9 | </head> |
paulb@354 | 10 | <body> |
paulb@354 | 11 | <h1>Integrating with Other Systems</h1> |
paulb@354 | 12 | <p>Most Web applications are not self-contained - instead of |
paulb@354 | 13 | providing information which is written into the application |
paulb@354 | 14 | code itself, they may often access data from other places or even |
paulb@354 | 15 | communicate with other systems. Since applications may be very |
paulb@354 | 16 | different in the way that they access external systems or the way |
paulb@354 | 17 | in which they obtain external information, WebStack does not mandate |
paulb@354 | 18 | rigid mechanisms for hooking into such systems or loading such |
paulb@354 | 19 | information. Instead, it is recommended that applications import |
paulb@354 | 20 | packages and modules which provide the functionality necessary to carry |
paulb@354 | 21 | out such integration.</p> |
paulb@354 | 22 | <h2>Examples of Packages</h2> |
paulb@354 | 23 | <p>Examples of packages and modules that might be used for integration |
paulb@354 | 24 | purposes include the following:</p> |
paulb@354 | 25 | <ul> |
paulb@354 | 26 | <li>Database access packages, including object-relational mappers.</li> |
paulb@354 | 27 | <li>Communications libraries - for connecting to Web services or |
paulb@354 | 28 | other remote services, for example.</li> |
paulb@354 | 29 | <li>Templating or reporting systems. (Note that templating systems |
paulb@354 | 30 | are also very useful when generating <a href="responses.html">responses</a>.)</li> |
paulb@354 | 31 | </ul> |
paulb@354 | 32 | <h2> Using External Packages</h2> |
paulb@354 | 33 | <p>In the simplest of cases, the use of external packages is as |
paulb@354 | 34 | straightforward as importing a Python module (or package) and then |
paulb@354 | 35 | using that module's contents. This can often be done in the <a |
paulb@354 | 36 | href="resources.html">resource</a> code; for example:</p> |
paulb@354 | 37 | <pre>import urllib<br /><br />class MyResource:<br /> def respond(self, trans):<br /> [Examine the transaction, decide what the user wants to do.]<br /><br /> f = urllib.urlopen("http://www.boddie.org.uk/rss/feed.xml")<br /><br /> [Produce some kind of response which tells the user what happened.]</pre> |
paulb@354 | 38 | <p>In the above example, here is what happens:</p> |
paulb@354 | 39 | <table style="text-align: left; width: 80%;" align="center" border="1" |
paulb@354 | 40 | cellpadding="5" cellspacing="0"> |
paulb@354 | 41 | <tbody> |
paulb@354 | 42 | <tr> |
paulb@354 | 43 | <th>What we do</th> |
paulb@354 | 44 | <th>Where it happens and how often</th> |
paulb@354 | 45 | </tr> |
paulb@354 | 46 | <tr> |
paulb@354 | 47 | <td align="undefined" valign="undefined"> Import <code>urllib</code> |
paulb@354 | 48 | to gain access to functionality which we can then use to access a |
paulb@354 | 49 | remote service.</td> |
paulb@354 | 50 | <td align="undefined" valign="undefined">This happens once - when |
paulb@354 | 51 | the above code is itself imported into Python.</td> |
paulb@354 | 52 | </tr> |
paulb@354 | 53 | <tr> |
paulb@354 | 54 | <td align="undefined" valign="undefined">Use the <code>urlopen</code> |
paulb@354 | 55 | function of <code>urllib</code> to actually access a remote service.</td> |
paulb@354 | 56 | <td align="undefined" valign="undefined">This happens in the |
paulb@354 | 57 | resource code each time the resource decides to access the service.</td> |
paulb@354 | 58 | </tr> |
paulb@354 | 59 | </tbody> |
paulb@354 | 60 | </table> |
paulb@354 | 61 | <p>In this case, the functionality is relatively easy to acquire and |
paulb@354 | 62 | does not require any initialisation. But what if we were connecting to |
paulb@354 | 63 | a database? There might be a need to specially initialise the database |
paulb@354 | 64 | module - only once, though - and then repeatedly use it. Consider this |
paulb@354 | 65 | highly artificial example:</p> |
paulb@354 | 66 | <pre>import mydb<br /><br />connection = mydb.connect("me", "myPassword")<br /><br />class MyResource:<br /> def respond(self, trans):<br /> [Examine the transaction, decide what the user wants to do.]<br /><br /> results = connection.query("feed", owner="boddie.org.uk")<br /><br /> [Produce some kind of response which tells the user what happened.] |
paulb@354 | 67 | </pre> |
paulb@354 | 68 | <p>In the above example, here is what happens:</p> |
paulb@354 | 69 | <table style="text-align: left; width: 80%;" align="center" border="1" |
paulb@354 | 70 | cellpadding="5" cellspacing="0"> |
paulb@354 | 71 | <tbody> |
paulb@354 | 72 | <tr> |
paulb@354 | 73 | <th>What we do</th> |
paulb@354 | 74 | <th>Where it happens and how often</th> |
paulb@354 | 75 | </tr> |
paulb@354 | 76 | <tr> |
paulb@354 | 77 | <td align="undefined" valign="undefined">Import the <code>mydb</code> |
paulb@354 | 78 | module to gain access to database access functionality.</td> |
paulb@354 | 79 | <td align="undefined" valign="undefined">This happens once - when |
paulb@354 | 80 | the above code is itself imported into Python.</td> |
paulb@354 | 81 | </tr> |
paulb@354 | 82 | <tr> |
paulb@354 | 83 | <td align="undefined" valign="undefined">Initialise a database |
paulb@354 | 84 | connection using the <code>connect</code> function from the <code>mydb</code> |
paulb@354 | 85 | module.</td> |
paulb@354 | 86 | <td align="undefined" valign="undefined">This also happens only |
paulb@354 | 87 | once - when the above code is itself imported into Python.</td> |
paulb@354 | 88 | </tr> |
paulb@354 | 89 | <tr> |
paulb@354 | 90 | <td align="undefined" valign="undefined">Use the <code>query</code> |
paulb@354 | 91 | method on the connection object to access a database.</td> |
paulb@354 | 92 | <td align="undefined" valign="undefined">This happens in the |
paulb@354 | 93 | resource code each time the resource decides to access the database.</td> |
paulb@354 | 94 | </tr> |
paulb@354 | 95 | </tbody> |
paulb@354 | 96 | </table> |
paulb@354 | 97 | <p>The choice of initialising the connection may seem arbitrary - why |
paulb@354 | 98 | not just obtain a connection in the resource? Usually, such decisions |
paulb@354 | 99 | are made on the basis of efficiency and on constraints outside the |
paulb@354 | 100 | control of the application - some database systems limit the number of |
paulb@354 | 101 | connections, for example, and if a large number of resources suddenly |
paulb@354 | 102 | became active, some of them would fail to obtain connections if the |
paulb@354 | 103 | connection initialisation code were in the <code>respond</code> |
paulb@354 | 104 | method of the resource.</p> |
paulb@354 | 105 | <h2>Configuring Packages Globally</h2> |
paulb@354 | 106 | <p>Of course, the above resource might not be the only resource to use |
paulb@354 | 107 | database connections. It might then be tempting to initialise a |
paulb@354 | 108 | connection for each module whose resource needs (or, since as normal |
paulb@354 | 109 | Python classes we can put many resources in a single module, whose |
paulb@354 | 110 | resources need) to access a database. But it would surely be more |
paulb@354 | 111 | convenient to define a single, central place to hold such global |
paulb@354 | 112 | resources.</p> |
paulb@354 | 113 | <p>One approach is to define a module which can be accessed by all |
paulb@354 | 114 | modules, and thus by all resources. Let us create such a module in the |
paulb@354 | 115 | file <code>Properties.py</code> which will reside alongside <code>MyApplication.py</code> |
paulb@354 | 116 | (or whatever the application module is called). Inside the <code>Properties</code> |
paulb@354 | 117 | module we can write the following code:</p> |
paulb@354 | 118 | <pre>import mydb<br /><br />connection = mydb.connect("me", "myPassword")</pre> |
paulb@354 | 119 | <p>Now, in each module containing resources which need to access the |
paulb@354 | 120 | database, all we need to do now is to import the <code>Properties</code> |
paulb@354 | 121 | module and to use the connection as defined in that module:</p> |
paulb@354 | 122 | <pre>import Properties<br /><br />class MyResource:<br /> def respond(self, trans):<br /> [Examine the transaction, decide what the user wants to do.]<br /><br /> results = Properties.connection.query("feed", owner="boddie.org.uk")<br /><br /> [Produce some kind of response which tells the user what happened.]</pre> |
paulb@354 | 123 | <p>This is a very simple approach that is technically outclassed by the |
paulb@354 | 124 | mechanisms available in some frameworks. Currently, WebStack does not |
paulb@354 | 125 | provide access to those more sophisticated mechanisms, however.</p> |
paulb@354 | 126 | </body> |
paulb@354 | 127 | </html> |