Webapp Module/Saxon

From EXPath Community Group

Servlex is the implementation of the EXPath Webapp module using Java Servlet technology for the server part, and Saxon and Calabash for the XSLT, XQuery and XProc processing.

Configuration

Servlex can be downloaded from its Google Code project.

Servlex is a typical Java EE web application, relying only on the Servlet specification. It uses an EXPath repository on the disk. The exact location of the repository is read via the system property org.expath.servlex.repo (this is the directory at the root of the repository). For Tomcat, you can set the property by adding the following to the global catalina.properties file:

org.expath.servlex.repo=/some/path/to/servlex/repo

For Tomcat on a server, the following security permissions should also be set (in the policy file):

grant codeBase "file:${catalina.base}/webapps/servlex/-" {
    // the repository dir
    permission java.io.FilePermission "/some/path/to/servlex/repo/-", "read";
    // commons xml resolver does read those properties
    permission java.util.PropertyPermission "xml.catalog.*", "read";
    permission java.util.PropertyPermission "user.dir", "read";
    // if you use the http client module within the stylesheets
    permission java.util.PropertyPermission "org.expath.hc.http.version", "read";
    permission java.net.NetPermission "getProxySelector";
    permission java.net.SocketPermission "site-accessed.com", "resolve,connect";
};

Once you've deployed the WAR in your application server, you can see if everything is fine by accessing the application page. For instance, if you use Tomcat locally on http://localhost:8080/, just navigate to http://localhost:8080/servlex/.

Google App Engine

Servlex can be deployed on Google App Engine. Because GAE does not allow the webapp to access the file system, Servlex cannot use the on-disk repository. Instead, the repository must be in the classpath. A script allows you to do it automatically.

Let's see how to call it in the simplest form. If your webapp project has the following structure on disk (i.e. following the EXPath Project structure):

my-webapp/
    dist/
        my-webapp-1.0.0.xaw
    src/
        ...
    xproject/
        appengine-web.xml
        expath-web.xml
        project.xml

Providing the GAE descriptor (that is, appengine-web.xml) sets the property org.expath.servlex.repo.classpath to the value org.expath.servlex.repo.appengine, then from the top-level directory, you can call the script like the following (relying on default values for all other options, and where servlex.war is the WAR file from the Servlex release):

servlex-appengine --servlex .../servlex.war dist/my-webapp-1.0.0.xaw

This wil create the directory dist/servlex-appengine-war/, which you can upload using the GAE SDK script's appcfg.sh:

APPENGINE_SDK/bin/appcfg.sh update dist/servlex-appengine-war/

For the basic usage, that's all you need to know. In order to adapt this to your real-life project, you might need to know in further details what's going on under the hood. What this script does is the following:

  • unzip the WAR file to the destination directory
  • create a new, empty, temporary repository for EXPath packages (that is, XAR and XAW files)
  • deploy every packages you give on the command line to this temporary repository
  • zip this repository into a JAR file
  • put this JAR file, as well as your GAE descriptor to the destination directory (that is, within the unzipped WAR)

Doing so, the repository is then accessible through the classpath, using a specific Java package prefix. By default this is org.expath.servlex.repo.appengine, but you can adapt it. In any case, this must be set as the value of the system property org.expath.servlex.repo.classpath in the GAE descriptor. A minimal descriptor is then (along with other required values from GAE):

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">

   <application>yourid</application>
   <version>0</version>

   <precompilation-enabled>false</precompilation-enabled>

   <system-properties>
      <property name="org.expath.servlex.repo.classpath" value="..."/>
   </system-properties>

</appengine-web-app>

Note the precompilation is disabled. This is because of an incompatibility between GAE precompilation and signed JARs, as Saxon is.

The complete list of options for the scripts (besides the option --help to display the help message) is:

servlex-appengine [--servlex ...] [--dir ...]? [--desc ...]? [--xrepo ...]?
                  [--pkg ...]? [--jar ...]? [--tmp ...]?
                  <list of XAR and XAW files...>

--servlex     path to the Servlex WAR file
--dir         the target directory to create the exploded WAR into
--desc        path to the GAE appengine-web.xml descriptor
--xrepo       path to the xrepo command (by default in the PATH)
--pkg         Java package name to put the in-classpath-repository in
--jar         the name of the JAR file to create for the repository
--tmp         a working directory to create files (by default a tmp dir)