docs.roxen.comBack to normal mode
DocsRoxenWebServer 3.3System Developer Manual JavaMore module examples
Copyright © 2004, Roxen Internet Software
Suggestions, comments & compliments
manuals@roxen.com

More module examples

A simple tag without contents

In this example we will create an RXML tag that outputs the company name. By updating the company name in the module, and then reloading the module, the change will occur everywhere that the tag has been used in the site. So this could be one way of implementing a string constant. (Another way would be to define it in an XSLT template, of course.) The module is installed exactly the same way as the Uppercase Tag module from the first example.

Notice the difference in the method queryTagFlags(), where we tell the parser that there should be no contents.

Source code for CompanyName.java
import com.roxen.roxen.*;
import java.util.Map;

public class CompanyNameTag extends Module
    implements ParserModule, SimpleTagCaller {

    public String info() {
        return "RXML empty tag that returns the company name.";
    }

    public String queryName() {
        return "Company Name";
    }

    public SimpleTagCaller[] querySimpleTagCallers() {
        return new SimpleTagCaller[] { this };
    }

    public String queryTagName() {
        return "companyname";
    }

    public int queryTagFlags() {
        return FLAG_EMPTY_ELEMENT;
    }

    public String tagCalled(String tag,
                            Map args,
                            String contents,
                            RoxenRequest req,
                            Frame frame) {

        return "Roxen Internet Software AB";
    }
}

Adding and using an admin variable

To improve the companyname tag, we would like to be able to change the string. One way of doing this is by introducing a variable in the administrative interface. This is accomplished by adding a constructor. There you put tasks to be performed when the class is loaded, for example the defvar() method. More information is in the code comments.

There are a number of constants in the class Module to set the type of the variable. All of these are not yet mapped to Java classes, but they are there for future compatibility. For the moment, we only recommend the use of TYPE_STRING and TYPE_FLAG.

Source code for VariableCompanyNameTag.java

import com.roxen.roxen.*;
import java.util.Map;

public class VariableCompanyNameTag extends Module
    implements ParserModule, SimpleTagCaller {

    public VariableCompanyNameTag() {
     /* Parameters to the defvar function:
        String var, Object value, String name, int type, String doc
        The parameter name has the format "tabname:label"
        If there is no colon, the default tab 'settings' is used */
        defvar("companyName", "Roxen IS AB",
               "Company Name ", TYPE_STRING,
               "Company name - Default value: \"Roxen IS AB\".");
    }

    public String info() {
        return "RXML tag that returns a variable company name.";
    }

    public String queryName() {
        return "Variable Company Name";
    }

    public SimpleTagCaller[] querySimpleTagCallers() {
        return new SimpleTagCaller[] { this };
    }

    public String queryTagName() {
        return "var-companyname";
    }

    public int queryTagFlags() {
        return FLAG_EMPTY_ELEMENT;
    }

    public String tagCalled(String tag, Map args,
                            String contents,
                            RoxenRequest req, Frame frame) {

        String company = (String)query("companyName");
        if (company != null) return company;
        /* else */ return "";  
    }
}

Addressing variables from other modules

At times you might need to get the value from a variable belonging to another module. You reach other modules by using a provider module. In this example we create a module whose sole purpose is to provide common parameters, where the class is called ParameterProvider. We then show the code lines needed to access the parameter from another module

Source code for ParameterProvider.java

import com.roxen.roxen.*;

public class ParameterProvider
       extends Module implements ProviderModule {

    /* **************************** *
     *         Constructor          *
     * **************************** */

    public ParameterProvider () {
        defvar("productString", "Roxen CMS", "productString", 
               TYPE_STRING, "Product name");
    }

    /* **************************** *
     *     Methods from Module      *
     * **************************** */

    /**  Returns the name of this module */
    public String queryName() {
        return "Parameter Provider";
    }

    /** Returns a short description of this module */
    public String info() {
        return "Contains parameters reachable from other modules.";
    }

    /* **************************** *
     * Methods from ProviderModule  *
     * **************************** */

    /**  Returns the identifier of this provider */
    public String queryProvides() {
        return "commonParameters";
    }
}

Code to reach an external variable in ParameterProvider from other modules

Module params = myConfiguration().getProvider("commonParameters");
String product = params.query("productString");

A useful tag showing incoming parameters

To understand the incoming parameters to the tagCalled-function, and for debugging purposes, it can be useful with a module that outputs these parameters. In addition to the previous examples, this module contains one new method:

  • The method start(), with tasks to be performed when the module is started.

Source code for JavaDebugLightTag.java

import com.roxen.roxen.*;
import java.util.*;

public class JavaDebugLightTag
       extends Module implements ParserModule, SimpleTagCaller {

    int callCount;
    StringBuffer resp;

    /* **************************** *
     *         Constructor          *
     * **************************** */

    /** The constructor is intially called when the modul is loaded.
        For example, register variables for the admin interface */
    public JavaDebugLightTag() {

     /* parameters to the defvar function:
        String var, Object value, String name, int type, String doc
        The parameter name has the format "tabname:label"
        If no colon is present, default tab 'settings' is used
        There are 19 valid types, but here we show use only two:
        TYPE_STRING and TYPE_FLAG */

     /* The first variable will appear under default tab 'Settings' */
        defvar("myString", "Roxen", "myString", TYPE_STRING,
               "String admin variable. " +
               "Default value: \"Roxen\".");

     /* The second variable will appear under a tab called 'Flags'.
        A flag has the value "1" when set and null when unset. */
        defvar("myFlag", null, "Flags: myFlag", TYPE_FLAG,
               "An example admin variable in the form of a flag.");
    }

    /* **************************** *
     *     Methods from Module      *
     * **************************** */

    /**  Returns the name of this module */
    public String queryName() {
        return "Java Debug Light Tag";
    }

    /** Returns a short description of this module */
    public String info() {
        return "A demo Java module for outputing some parameters.";
    }

    /** Intial things to do when the module is started.
        For example, initiate variables or write to the log */
    protected void start() {
        callCount = 0;
    }

    /* **************************** *
     *  Methods from ParserModule   *
     * **************************** */

    /** Returns one instance of each RXML tag class (SimpleTagCaller)
        handled by this parser module. */
    public SimpleTagCaller[] querySimpleTagCallers() {
        return new SimpleTagCaller[] { this };
    }

    /* **************************** *
     * Methods from SimpleTagCaller *
     * **************************** */

    /** Returns the name of the tag handled by this tag caller. */
    public String queryTagName() {
        return "javadebuglight";
    }

    /** Returns one or more mode flags for this tag caller. */
    public int queryTagFlags() {
        /* Valid flags: FLAG_NONE, FLAG_EMPTY_ELEMENT, 
           FLAG_NO_PREFIX, FLAG_PROC_INSTR, FLAG_DONT_PREPARSE, 
           FLAG_POSTPARSE, FLAG_STREAM_RESULT, FLAG_STREAM_CONTENT, 
           FLAG_DEBUG */
        return FLAG_NONE;
    }

    /** Evaluates a result for the call to this tag caller. */
    public String tagCalled(String tag, Map args, String contents,
                            RoxenRequest id, Frame frame) {
        /* tag -      the name of the tag (javadebuglight)
           args -     all attributes/value-pairs from the start tag
           contents - all contents between the start and the end tag
           id -       the Roxen request object
           frame -    the RXML parse frame  */

        callCount++;
        resp = new StringBuffer();

        /* Class variables */
        resp.append("<b>CLASS VARIABLES</b><br/>");
        resp.append("Call Count=" + callCount + "<br/>");

        /* Element variables */
        resp.append("<br/><b>ELEMENT VARIABLES</b><br/>");
        resp.append("tag=" + tag + "<br/>");
        resp.append("args=" + args + "<br/>");
        resp.append("contents=" + contents + "<br/>");






        /* Admin variables */
        resp.append("<br/><b>ADMIN VARIABLES</b><br/>");
        resp.append("myString: " + query("myString") + "<br/>");
        if (query("myFlag") != null) {
            resp.append("Admin variable 'myFlag' is set " +
                        "(Value=" + query("myFlag") + ")<br/>");
	    } else {
            resp.append("Admin variable 'myFlag' is unset<br/>");
        }

        /* URL parameter test */
        resp.append("<br/><b>URL PARAMETER TEST</b><br/>");
        // Check the URL for parameter ?cmd=save
        if (id.variables().containsKey("cmd")) {
            if (id.variables().get("cmd").toString().equals("save")){
                resp.append("URL contains 'cmd=save' <br/>");
            } else {
                resp.append("URL parameter 'cmd' is "
                          + "something else than 'save'<br/>");
            }
        } else {
            resp.append("URL does not contain parameter 'cmd'<br/>");
        }

        /* some module class methods */
        resp.append("<br/><b>MODULE CLASS METHODS</b><br/>");
        resp.append("Internal location: " 
                   + queryInternalLocation() + "<br/>");
        resp.append("Status: " + status() + "<br/>");

        /* some client request variables */
        resp.append("<br/><b>CLIENT REQUEST VARIABLES</b><br/>");
        resp.append("Client IP: " + id.remoteaddr + "<br/>");
        resp.append("Raw URL: " + id.rawURL + "<br/>");
        resp.append("Request variables: " + id.variables() 
                  + "<br/>");
        resp.append("Remote address: " + id.remoteaddr + "<br/>");
        resp.append("Request time: " + new Date(id.time) + "<br/>");

        resp.append("<br/>Raw request:<br/>" + id.raw 
                  + "<br/><br/>");

        /* some client request methods */
        resp.append("<br/><b>CLIENT REQUEST METHODS</b><br/>");
        resp.append("Cookies:<br/>" + id.cookies() + "<br/><br/>");
        resp.append("Supported:<br/>" + id.supports() + "<br/>");


        /* Evaluation is finished - return the result */
        return RoxenLib.parseRXML(resp.toString(), id);
    }
}

A module containing more than one class file

So far we have implemented each module as a class file of its own. This is possible, but the preferred way is to install a module as a jar-file, perhaps implementing several tags in one and the same module. As an example we will have one module containing the two tags <uppercase></uppercase> and <companyname/>.

What we need:

  • Two classes that implement SimpleTagCaller.

  • A separate class that implements ParserModule.

  • A manifest file.

  • To create the jar-file.

We now also have a package structure for our classes. The jar file will be created in the top directory 'myproject' in this example

Directory and file structure

- myproject (dir)
  - classes (dir)
    Manifest
    - com (dir)
      - roxen (dir)
        - examples (dir)
          JavaTags.class
          CompanyNameTag.class
          UpperCaseTag.class

Source of Manifest file

Name: Roxen Java RXML tag module
Main-Class: com.roxen.examples.JavaTags

Note!

The Manifest file must end with a line feed, which means you must press Enter at the end of the line defining 'Main Class' before saving the file.

In the directory where you have saved the Manifest file, create the JavaTags.jar file by typing the following on the command line.

jar -cvfm ../JavaTags.jar Manifest com

Source of CompanyNameTag.java

package com.roxen.examples;

import com.roxen.roxen.*;
import java.util.Map;

public class CompanyNameTag implements SimpleTagCaller {

    public String queryTagName() {
        return "companyname";
    }

    public int queryTagFlags() {
        return FLAG_EMPTY_ELEMENT;
    }

    public String tagCalled(String tag, Map args, String contents,
                            RoxenRequest req, Frame frame) {

        return "Roxen Internet Software AB";
    }
}
Source of UpperCaseTag.java 
package com.roxen.examples;

import com.roxen.roxen.*;
import java.util.Map;

public class UppercaseTag implements SimpleTagCaller {

    public String queryTagName() {
        return "uppercase";
    }

    public int queryTagFlags() {
        return FLAG_NONE;
    }

    public String tagCalled(String tag, Map args, String contents,
                            RoxenRequest req, Frame frame) {

        return contents.toUpperCase();
    }
}

Source of JavaTags.java
package com.roxen.examples;

import com.roxen.roxen.*;
import java.util.Map;

public class JavaTags extends Module implements ParserModule {

    public String info() {
        return "Java module for new RXML tags.";
    }

    public String queryName() {
        return "Java RXML Tags";
    }

    public SimpleTagCaller[] querySimpleTagCallers() {
        SimpleTagCaller[] tagArray = new SimpleTagCaller[2];
        tagArray[0] = new CompanyNameTag();
        tagArray[1] = new UppercaseTag();
        return tagArray;
    }
}