Questions


Table of Contents

Resource Scripts
What is a resources script?
What kinds of elements can appear in a resources script?
What are the rules for referring to a named resource?
How do I organize resource scripts as they get bigger?
Can I define my own property and named resource elements and use them interchangeably with existing ones in resource scripts?
Requests
Where do I put the code to validate a servlet request?
Parameters
If my servlet is sent a request like /bookstore/pages/books?category=C, how can my dynamic content handler access the category parameter?
What happens if the request is /bookstore/pages/books?category=C&category=F, and I want my dynamic content handler to be passed both values?
What do I do if my servlet is sent /bookstore/pages/books?category-code=C, where the parameter category-code does not follow Java mixed-case naming conventions, yet I want to pass it in a dynamic content handler?

Resource Scripts

What is a resources script?

A resources script provides a catalog of named pages that encapsulate a service of some kind. A page is associated with actions - transforming XML to HTML through the application of a stylesheet, serializing XML to PDF, transforming a flat file to XML, updating records in a database, and so forth.

What kinds of elements can appear in a resources script?

Basically, three kinds:

  • properties - elements that affect the execution of instructions within a scope,
  • named resources - resources that can be referenced by name elsewhere in the script, and
  • annonymous resources - elements that appear in place inside other elements.

The example below shows two named resources (the px:content elements), and two properties (the px:cachingOptions elements.)


<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
                     
  <px:cachingOptions caching="no"/>      
  
  <px:systemContent name="books" href="documents/books.xml"/>
  
  <px:systemContent name="authors" href="documents/books.xml">
    <px:cachingOptions caching="yes"/>      
  </px:systemContent>

</px:resources>

In this example, the default rule is set so that there is no caching of content. In particular, the books document is not cached. The authors document, on the other hand, is cached.

What are the rules for referring to a named resource?

Let's use the following resources script as an example.


<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
  
  <px:page name="pipeline">
    <px:show>
      <px:transform>
        <px:systemContent href="documents/mixed-up.xml"/>
        <px:saxFilter className="PreFilter"/>
        <px:style href="styles/filter.xsl"/>     
        <px:saxFilter className="PostFilter"/>     
      </px:transform>
    </px:show>
  </px:page>

</px:resources>

This script contains one top level named resource - a page - and four annonymous resources in the content of the page - an XML file, pre and post SAX filters, and an XSLT stylesheet. Note that the top level page resource has the "name" attribute. This is the local name of the page resource. The full name of the resource consists of a namespace and a local name. In the example above, the namespace is empty.

Annonymous resources cannot be reused in the definition of other pages. Therefore it is useful to make them top level named resources and refer to them by reference. We can do this as follows.


<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
  
  <px:systemContent name="mixed-up" href="documents/mixed-up.xml"/>
  
  <px:page name="pipeline">
    <px:show>
      <px:transform>
        <px:content ref="mixed-up"/>
        <px:filter ref="pre-filter"/>
        <px:style ref="xsl-filter"/>     
        <px:filter ref="post-filter"/>     
      </px:transform>
    </px:show>
  </px:page>
  
  <px:saxFilter name="pre-filter" className="PreFilter"/>
  <px:style name="xsl-filter" href="styles/filter.xsl"/>     
  <px:saxFilter name="post-filter" className="PostFilter"/>

</px:resources>

Named resources, in addition to being referenced with an actual name, can be referenced through parameter values. This is illustrated in the example below.


<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
  
  <px:systemContent name="mixed-up" href="documents/mixed-up.xml"/>
  
  <px:parameter name="my-param">mixed-up</parameter>
  
  <px:page name="still-mixed-up">
    <px:show>
      <px:transform>
        <px:content ref="$my-param"/>
      </px:transform>
    </px:show>
  </px:page>

</px:resources>

If two resources are of different types, e.g. content and filter, they can have the same name and there is no conflict. If two resources have the same type, however, such as an XSLT stylesheet and a SAX filter, there is a conflict. We can, however, have two resources of the same type with the same local names if they belong to different namespaces.

The example below shows how to set the namespace for a resource and how to refer to one by its fully qualified name. The namespace is specified by a "ns" attribute. Note that if a resource element does not have the "ns" attribute, its namespace defaults to the namespace of its nearest ancestor that does have a "ns" attribute. Also note that the order in which the top level instructions appear in the document does not matter. The px:systemContent element, for example, may appear below or above the px:page element that refers to it.


<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
              xmlns:myapp="http://www.presentingxml.com/myapp"
              xmlns:mystyle="http://www.presentingxml.com/myapp/style"
              ns="http://www.presentingxml.com/myapp">
  
  <px:systemContent name="mixed-up" href="documents/mixed-up.xml"/>
  
  <px:page name="pipeline">
    <px:show>
      <px:transform>
        <px:content ref="myapp:mixed-up"/>
        <px:filter ref="myapp:pre-filter"/>
        <px:style ref="mystyle:xsl-filter"/>     
        <px:filter ref="myapp:post-filter"/>     
      </px:transform>
    </px:show>
  </px:page>
  
  <px:saxFilter name="pre-filter" className="PreFilter"/>
  <px:style ns="http://www.presentingxml.com/myapp/style"
            name="xsl-filter" href="styles/filter.xsl"/>     
  <px:saxFilter name="post-filter" className="PostFilter"/>

</px:resources>

How do I organize resource scripts as they get bigger?

As a resources script becomes bigger, it becomes desirable to reorganize it, perhaps splitting off the content and style elements into separate files, in separate directories. For example, we may wish to have the directory tree:

  • pages - Directory containing the resources.xml file.
  • documents - Directory containing the documents.xml file.
  • styles - Directory containing the styles.xml file, with subdirectories containing the actual stylesheets.
The document and style definitions are now contained in two separate files, documents.xml and styles.xml. We need to import these definitions in the pages.xml file, and we do that using the include instruction.


  
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
              xmlns:myapp="http://www.presentingxml.com/myapp"
              xmlns:mystyle="http://www.presentingxml.com/myapp/style"
              ns="http://www.presentingxml.com/myapp">
  
  <px:include href="../documents/documents.xml"/>
  <px:include href="../styles/styles.xml"/>
  
  <px:page name="pipeline">
    <px:show>
      <px:transform>
        <px:content ref="myapp:mixed-up"/>
        <px:filter ref="myapp:pre-filter"/>
        <px:style ref="mystyle:xsl-filter"/>     
        <px:filter ref="myapp:post-filter"/>     
      </px:transform>
    </px:show>
  </px:page>
  
  <px:saxFilter name="pre-filter" className="PreFilter"/>
  <px:saxFilter name="post-filter" className="PostFilter"/>

</px:resources>

Can I define my own property and named resource elements and use them interchangeably with existing ones in resource scripts?

Yes. Property and named resource elements must be registered in the components.xml file that currently resides in the resource directory of the presentingxml project (a more decentralized approach is planned for the future.)

Any component that satisfies the contract of a pipeline, action, filter, content, or other component can be used interchangeably in the script with like components. You can also define new kinds of components that you can use within your own components.

User defined components should be assigned to their own namespace (not the Presenting XML namespace.)

Requests

Where do I put the code to validate a servlet request?

Do the following:

  • Implement a dynamic content handler, and put the validation code there. Throw a com.presentingxml.components.content.PresentingXMLFault exception if validation fails.
  • Define a page with a simple pipeline consisting of the dynamic content. Enclose the dynamic content in a px:localRedirect element to transfer to the requested page if validation succeeds. Optionally, provide a px:doFault element to handle the fault by transferring to an error page.
  • Put a px:validateRequest element inside the px:app element, with a px:page element referencing the page that does the validation. The page referred to by the px:validateRequest will be invoked as soon as a URI request is received.

To implement the dynamic content handler that actually performs the validation, you need to implement the tagging interface com.presentingxml.components.content.dynamic.RequestHandler. You will need to provide a method called doRequest that takes three arguments:

  • A com.presentingxml.components.PageContext.
  • Any user defined interface that follows bean naming conventions for accessors. This is to receive parameters that have been passed with the URI request.
  • A com.presentingxml.components.content.ContentWriter. You only need to write to this if you need elements to be matched against when you construct the request URI to transfer to in the px:localRedirect element.

An example of a RequestHandler implementation is shown below.


  public class BookstoreGatekeeper implements RequestHandler {
    public void doRequest(PageContext context, Login login, ContentWriter writer) 
    throws PresentingXMLException {
      //  Put code to validate servlet request here
    }
  }
  
  interface Login {
    String getUserId();
    String getPassword();
  }

The resources script that puts all this together will look as follows.



<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
              xmlns:myapp="http://www.presentingxml.com/myapp"
              ns="http://www.presentingxml.com/myapp">
  
  <px:app name="bookstore">
    <px:validateRequest><px:page ref="myapp:bookstore-gatekeeper"/></px:validateRequest>
    
    <px:mapRequest> 
      <!-- device and request URI matchers -->
    </px:mapRequest>      

  </px:app>
  
  <px:page name="bookstore-gatekeeper">
    <px:show>
      <!-- px:requestURI is a built-in variable that holds the value of the original request URI -->
      <px:localRedirect select="$px:requestURI">
        <px:dynamicContent className="samples.common.BookstoreGatekeeper"/>        
      </px:localRedirect> 
    </px:show>
  </px:page>
  
  <!-- other resource definitions -->
  
</px:resources>

Parameters

If my servlet is sent a request like /bookstore/pages/books?category=C, how can my dynamic content handler access the category parameter?

First, the px:page element that defines the books page must contain a px:parameter element,


  <px:page name="books">
    <px:parameter ns="" name="category"/>

Now suppose we implement a SelectHandler to service a request for article titles, something like


public class BookCatalog implements SelectHandler {
  public void doRequest(PageContext context, Book parameters, 
  ContentWriter contentWriter) throws PresentingXMLException {
    //  Implementation here
  }
}

Note the second argument in the doRequest method, parameters, which we have declared to be of type Book. This interface is defined as follows:

public interface Book {
  public String getCategory();
}

Now, if within the doRequest method we call the getCategory method on the Book interface, and if the HTTP request to the servlet has a parameter category, then the getCategory method will return the value of that parameter. It will return null if there is no parameter.

The mapping from request parameters to method invocations on an interface is done automatically according to bean naming conventions using the Java proxy classes.

What happens if the request is /bookstore/pages/books?category=C&category=F, and I want my dynamic content handler to be passed both values?

The px:parameter element will be the same,


  <px:page name="books">
    <px:parameter ns="" name="category"/>

The Book interface will need to be written as follows:


public interface Book {
  public String[] getCategory();
}

The parameter values will still be mapped correctly to the string array if the request conatins only one category value or no category value.

What do I do if my servlet is sent /bookstore/pages/books?category-code=C, where the parameter category-code does not follow Java mixed-case naming conventions, yet I want to pass it in a dynamic content handler?

Use the select attribute of the px:parameter element,


  <px:page name="books">
    <px:parameter ns="" name="category" select="category-code"/>

Note that the same request parameter may be mapped into more than one parameters.