What is X:Forge?

X:Forge is an XML language whose main focus is on dynamic XML generation. X:Forge tags are supposed to be included in XML documents for further processing. The tool was designed as a replacement for XSP, an Apache technology originally used for dynamic generation of XML content in the Cocoon Project. From a higher level view X:Forge is also a framework to design XML-based applications using Avalon's component technology and Inversion of Control pattern.

Basics

Version Information

This documentation applies to version 3.0 of X:Forge, which is not released yet. However, as it is deemed stable and has more features than 2.0, it is the recommended version to use and can be downloaded from CVS by checking out with the tag xforge_3_0_branch.

Technology

X:Forge is a method to dynamically generate XML content based on runtime parameters (such as client requests and so on) and application logic. The main purpose doesn't differ from technologies such as XSP, but the implementation is peculiar since it's heavily component based.

The architecture clearly defines three different environments:

  1. Business logic components (typically written using a programming language);
  2. Component maps that associate business logic to specific environments providing named components to be used as arguments by markup code;
  3. A simple markup used to dynamically call the named components and pass parameters.

Another major advantage of X:Forge is the capability of accessing (user defined) context elements via a generic broker mechanism. As an example in a typical servlet environment this means that the business logic can have transparent access to the whole servlet environment.

Namespaces

Namespace URI of X:Forge itself:
http://xforge.org/xforge/3.0/

Namespace URI of an automated component that is mapped to the namespace prefix foo:
http://xforge.org/xforge/3.0/automation/foo

Namespace URI of an X:Forge context defined in class org.bibop.xml.xforge.helpers.ThreadContext:
http://xforge.org/xforge/3.0/context/org.bibop.xml.xforge.helpers.ThreadContext

Structure

A typical X:Forge setup consists of the following:

  1. An XML processing framework which will, in a general way, handle XML content and hand it to the X:Forge environment. X:Forge has been designed with Cocoon in mind, but very little work is required to use it in other (SAX or DOM based) environments;
  2. Some X:Forge components, or even plain Java classes to be called via a generic reflection/mapping mechanism;
  3. A configuration file which maps the components/classes to named aliases and configures the execution environment.

Sample Usage

Syntax

The syntax for X:Forge is pretty straightfoward. There is a separate document that lists all the tags available. Here are two of them:

  • xf:process
  • xf:parameter

A typical X:Forge enabled document looks like this:

<?xml version="1.0"?>

<page xmlns:xf="http://xforge.org/xforge/3.0/">

  Hi, I'm the first X:Forge enabled page ever. My first message is:
  <xf:process using="HelloWorld"/>

</page>

This will turn out, after processing, in:

<?xml version="1.0"?>

<page xmlns:xf="http://xforge.org/xforge/3.0/">

  Hi, I'm the first X:Forge enabled page ever. My first message is:
  Hello, World!

</page>

Now a slightly more complicated example, using runtime parameters:

<?xml version="1.0"?>

<page xmlns:xf="http://xforge.org/xforge/3.0/">

  I'm the smartest X:Forge enabled page ever. My first message is: 
  <xf:process using="HelloWorld">
    <xf:parameter name="greeting">Hello XML World!</xf:parameter>
 </xf:process>

</page>

It's easy to imagine what the output will be:

<?xml version="1.0"?>

<page xmlns:xf="http://xforge.org/xforge/3.0/">

  I'm the smartest X:Forge enabled page ever. My first message is:
  Hello XML World!

</page>

X:Forge calls can of course be nested, allowing dynamic assembly of XML data:

<?xml version="1.0"?>

<page xmlns:xf="http://xforge.org/xforge/3.0/">

  I'm the smartest XForge enabled page ever. My first message is: 
  <xf:process using="HelloWorld">
    <xf:parameter name="greeting">
      <xf:process using="GreetingsDB">
        <xf:parameter name="query">getGreeting</xf:parameter>
      </xf:process>
    </xf:parameter>
  </xf:process>

</page>

Behind the Scenes

When the X:Forge implementation (a generic SAX ContentHandler or, in the case of Cocoon 2 a Sitemap transformer) hits a xf:process element it looks in the configuration file to see if there is a configured component for the content of the "using" attribute.

The X:Forge component should implement the XForgeComponent interface and encapsulate the business logic into a toSax() method which is responsible for sending SAX events to the designated ContentHandler. The code for the above examples will be something like this:


package org.bibop.xml.xforge.components.examples;

import org.xml.sax.SAXException;
import org.bibop.xml.xforge.components.AbstractXForgeComponent;
import java.io.Serializable;

public class HelloWorldComponent extends AbstractXForgeComponent {

    public void toSax () throws SAXException {

        String hello = "Hello World ";

        if (this.parameters.containsKey("greeting"))
          output((String)this.parameters.get("greeting"));
        else
          output(hello);
    }
}

The compiled class is then declared in the configuration file (actually an Avalon Configuration object) and configured. The configuration file will look like this:


<?xml version="1.0" encoding="UTF-8"?>

<xforge>

  <components>

    <component role="process" 
               class="org.apache.avalon.excalibur.component.DefaultComponentSelector"
               logger="xforge">
      <component-instance
               name="HelloWorld" 
               class="org.bibop.xml.xforge.components.examples.HelloWorldComponent"
               logger="test"/>
    </component>

  </components>

<role-list>
  <role name="org.apache.avalon.framework.component.ComponentSelector"
        shorthand="process"
        default-class="org.apache.avalon.excalibur.component.DefaultComponentSelector"/>
</role-list>

</xforge>

When the "HelloWorld" component is found, an instance is created (or taken from an existing pool depending on the configuration) and its toSax() method is called. The SAX events are then sent to the (user defined) ContentHandler for further processing.

The logger attribute here refers to a logger that was defined in another configuration file that follows the Avalon LogKit syntax. X:Forge includes a standard configuration file under org/bibop/xml/xforge/logkit.xconf, which is used by the supplied test application (see README file in root directory of download for details).