Developing Zen Applications
Zen Applications
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

A Zen application specifies the full set of activities that can result when a Zen client and server interact. These activities may consist of displaying web pages, issuing queries to a database, writing data to disk, and more. When you create a Zen application, you create a suite of Zen classes that specify these activities. The language you use for these classes is Caché ObjectScript — with embedded snippets of XML, HTML, SVG, and JavaScript as needed.

This chapter explores Zen application programming based on the foundation provided by Using Zen. It provides the following topics:
Zen Classes as CSP Classes
The base application class %ZEN.application and the base page class %ZEN.Component.page each inherit from %CSP.page. This means that every Zen application class and every Zen page class is also an instantiable Caché Server Page. All the CSP page class properties, methods, parameters, and variables (such as %session) are available to Zen application and page classes.
Important:
Experienced CSP programmers should note there are important differences between Zen and CSP classes. For example, the allowed expressions that can appear within #()# syntax is much more restrictive in Zen than it is in CSP. For details, see the section Zen Runtime Expressions.”
Zen Application Configuration
A Zen application may require configuration of its Caché system settings. In order to accomplish this, you need to configure the web application associated with the Zen application. This section explains what this means, and how to perform the configuration steps.
Zen application code resides in a Caché namespace. Each Caché namespace has at least one web application mapped to it. By default, when you create a new namespace called myNamespace it comes with a web application already mapped to it. This web application has default settings already in place, including the following settings which are significant for Zen:
At compile time, a Zen application finds its associated web application and applies its configuration settings. That is, Zen cascades through the following sequence and returns the first web application that it finds:
  1. The Zen application knows which Caché namespace it resides in, for example myNamespace.
  2. If there is a web application in this namespace whose name is /csp/myNamespace, Zen uses the settings from this web application.
  3. If not, Zen searches for any web application mapped to myNamespace and returns one based on standard Caché global collation order. For example, if there are web applications /A and /X that map to myNamespace, Zen uses the settings from application /A.
Important:
There is no way to configure an explicit association between a Zen application and a web application. The simplest way to manage the implicit association is to keep each Zen application in its own Caché namespace that has no other application in it and, when you need to configure application settings, configure the default web application for that namespace.
Whether or not you actually need to configure web application settings depends on the features that you add to your Zen application. The beginning of this section lists the settings you most often need to adjust. When you need to configure web application settings, the basic procedure is as follows:
For High Availability solutions running over CSP, InterSystems recommends that you use a hardware load balancer for load balancing and failover. InterSystems requires that you enable sticky session support in the load balancer. This guarantees that — once a session has been established between a given instance of the gateway and a given application server — all subsequent requests from that user run on the same pair.
This configuration assures that the session ID and server-side session context are always in sync; otherwise, it is possible that a session is created on one server but the next request from that user runs on a different system where the session is not present, which results in runtime errors (especially with hyperevents, which require the session key to decrypt the request). To enable sticky session support, see your load balancer documentation.
Note:
It is possible to configure a system to work without sticky sessions, but this requires that the CSP session global be mapped across all systems in the enterprise and can result in significant lock contention so it is not recommended.
Zen Application Classes
A Zen application class is a class derived from %ZEN.application that provides high-level housekeeping and acts as the single root for all of the pages in the application. The application class does not keep an inventory of its associated pages. The association between the application and its pages occurs because every Zen page class has an optional parameter called APPLICATION that identifies the application class. This parameter is optional because an application class is optional. Your Zen application needs to provide an application class only if you consider it a useful convenience. However, if you do provide an application class, you may provide only one application class and every page in your application must identify this application using the APPLICATION parameter.
The following table lists the elements of a Zen application class.
Application Class Elements
Element Role Specific Items Description
Class parameters General application settings APPLICATIONNAME Defines a text string that you can use in titles or labels.
 
CSSINCLUDES Comma-separated list of Cascading Style Sheet (.css) files to include for every page in the application. You can use URLs or simple file names. If you use simple file names, the CSP Files Physical Path specifies the physical path to these files. For further information, see the section Zen Application Configuration.” For information about style sheets, see the Zen Style chapter in the book Using Zen.
HOMEPAGE
URI of a default Home Page for the application.
This makes it possible for the application class to be specified as a starting point for the application, even though it does not itself display a page. When the application class receives an HTTP request, it redirects the request to the URI specified by the HOMEPAGE class parameter.
JSINCLUDES Comma-separated list of JavaScript (.js) include files to include for every page in the application. You can use URLs or simple file names. If you use simple file names, the CSP Files Physical Path specifies the physical path to these files. For further information, see the section Zen Application Configuration.”
USERPACKAGES Comma-separated list of user-defined class packages whose HTML class and style definitions are in pre-generated include files. These include files are available to every page within the application.
USERSVGPACKAGES Comma-separated list of user-defined class packages whose SVG class and style definitions are in pre-generated include files. These include files are available to every page within the application.
An embedded XML document CSS style definitions XData Style Any CSS style definitions that appear within this XData block are placed on every page within the application. See the Zen Style chapter in the book Using Zen.
When programming, be aware that the application class can contain server-side methods written in ObjectScript, Caché Basic, or Caché MVBasic only. It cannot contain any client-side methods marked with the javascript keyword, or client/server methods marked with the ZenMethod keywords. The application class can execute methods on the server only.
Sample Development Project
The chapter Zen Layout in the book Using Zen explains how to use template pages and panes to organize layout and style for a Zen application. This topic traces an example that uses composites and dynamic page generation to organize behavior for a Zen application. This example uses Zen to add new order entry module pages to an existing Weblink application. Constraints are as follows:
The following example addresses these constraints. It purposely does not address layout or style but focuses on behavior.
Class TestMe.MainPage Extends %ZEN.Component.page
{
  /// Comma-separated list of User class packages whose HTML class
  /// and style definitions are in pre-generated include files.
  Parameter USERPACKAGES = "TestMe.Components";

  /// Class name of application this page belongs to.
  Parameter APPLICATION;

  /// Displayed name of this page.
  Parameter PAGENAME;

  /// Domain used for localization.
  Parameter DOMAIN;

  /// This Style block contains page-specific CSS style definitions.
  XData Style
  {
    <style type="text/css">
      /* style for title bar */
      #title {
        background: #C5D6D6;
        color: black;
        font-family: Verdana;
        font-size: 1.5em;
        font-weight: bold;
        padding: 5px;
        border-bottom: 1px solid black;
        text-align: center;
      }

      /* container style for group g1 */
      #g1 {
        border: 1px solid black;
        background: #DDEEFF;
      }

      /* container style for group g2 */
      #g2 {
        border: 1px solid black;
        background: #FFEEDD;
      }
    </style>
  }

  /// This XML block defines the contents of this page.
  XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ]
  {
    <page xmlns="http://www.intersystems.com/zen"
             xmlns:testme="TestMe"
             title="">
      <html id="title">TestMe Test Page</html>
      <vgroup id="gSearch" width="100%">
        <testme:searchForm/>
      </vgroup>
      <spacer height="40"/>
      <!-- these groups are containers for dynamically loaded components -->
      <hgroup>
        <vgroup id="g1"/>
        <spacer width="20"/>
        <vgroup id="g2"/>
      </hgroup>
    </page>
  }

  /// Create a form (via a composite element) and place it into the group with
  /// the id groupId. formClass is the name of the composite element
  /// containing the form. formId is the id applied to the form.
  ClientMethod loadForm(formClass, formId, groupId) [ Language = javascript ]
  {
    try {
      // if there is already a form, get rid of it
      var comp = zen(formId);
      if (comp) {
        zenPage.deleteComponent(comp);
      }

      var group = zen(groupId);
      var form = zenPage.createComponentNS('TestMe',formClass);
      form.setProperty('id',formId);
      group.addChild(form);
      group.refreshContents(true);
    }
    catch(ex) {
      zenExceptionHandler(ex,arguments);
    }
  }
}
Some important things to notice about the TestMe.MainPage class:
Now take a look at the components for the example. As suggested in Composite Components,” all of these composite component classes are placed together in their own package, TestMe.Components. The reason for this is that Zen automatically generates JS and CSS header files for components in a given package. By placing these components in a package you can exploit this feature by setting the parameter USERPACKAGES to the package name, on the main page, as shown above:
Parameter USERPACKAGES = "TestMe.Components";
The composites also use their own XML namespace to avoid conflict with other components.
The composite component classes are as follows: