Pittsburgh-NEH-Institute / pr-app

eXist-db app development

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Replace hard-coded paths with controller variables

djbpitt opened this issue · comments

Note on terminology

The description below uses the following eXist-db terminology:

  • collection: Technical eXist-db term for what is otherwise called a directory, subdirectory, or folder.
  • resource: Technical eXist-db term for what is otherwise called a file or document. Resources may be XML, XQuery, or any other filetype.

The issue

XQuery resources in the modules collection were originally written using hard-coded paths to the XML data resources (e.g., collection('/db/apps/pr-app/data/hoax_xml') for the collection of 36 newspaper articles). This works only if the user has installed the app in the default location (under /db/apps) and with the default name (pr-app). This is an unnecessary dependency that should be removed.

How to fix it

The controller has access to controller variables, which can be used to construct paths to app resources dynamically. Hard-coded paths should be replaced with dynamic ones in all XQuery modules. This enhancement has already been implemented in search.xql.

Implementation details

All XQuery modules should declare the following variables:

declare variable $exist:root as xs:string := request:get-parameter("exist:root", "xmldb:exist:///db/apps");
declare variable $exist:controller as xs:string := request:get-parameter("exist:controller", "/pr-app");
declare variable $path-to-data as xs:string := $exist:root || $exist:controller || '/data/hoax_xml';

I have configured controller.xql so that it automatically makes $exist:root and $exist:controller available to all modules, but the variables must also be declared within each XQuery module that seeks to use them. That is likely to be all XQuery modules in our app.

The first two lines above retrieve these values, defaulting to the default installation locations. The third line above uses the two controller variables to construct a path that (assuming installation into the default location and with the default app name) is equivalent to /db/apps/pr-app/data/hoax_xml. Other hard-coded paths (perhaps to documents using the doc() function) can be assembled, using similar logic, in any XQuery module that needs them.

Implementation notes

  1. The second argument to the request:get-parameter() function specifies a default value that will be used if no actual value is supplied. In normal use the actual values will always be available because they are supplied by the controller. For development purposes, though, it may be useful to execute an XQuery module without going through the controller. For example, navigating to http://localhost:8080/exist/apps/pr-app/search executes search.xql by using the controller, while navigating to http://localhost:8080/exist/apps/pr-app/modules/search.xql bypasses the controller and executes search.xql directly, and therefore uses the default values supplied by the variable declarations. Because we are revising our XQuery modules to remove hard-coded paths to app collections and resources, the default values in the variable declarations make those paths accessible even when an XQuery module is executed in a way that bypasses the controller.

  2. For more information about the controller variables see the eXist-db book, pp. 201 ff., but be aware that there is an error in figure 9.2 on p. 202 (/apps is not part of $exist:controller; the example at the top of that page, above the figure, is correct). We should all be comfortable with these details before the Institute sessions begin. You can verify the variable values in our app by navigating to http://localhost:8080/exist/apps/pr-app/controller-variables. This developer-only file does not specify default values, and therefore must be accessed through the controller (using the URL above) in order to return correct results (navigating to http://localhost:8080/exist/apps/pr-app/modules/controller-variables.xql, which bypasses the controller, will raise an error).

Done