Fork me on GitHub

Creating Custom Cache Configuration Namespaces

As a simple introduction to creating custom XML Cache Configuration Namespaces, let's create the traditional "Hello World" example, the goal of which is to output a greeting during the processing of a Cache Configuration file.

To achieve this we're going to create the greeting Namespace Content Handler that would me used as follows:

<cache-config xmlns:greeting="class://GreetingNamespaceContentHandler">

    ...

    <greeting:message>Hello World</greeting:message>

    ...

</cache-config>

The GreetingNamespaceContentHandler Implementation

To create the GreetingNamespaceContentHandler we need a class that implements the com.oracle.coherence.environment.extensible.NamespaceContentHandler interface.

import java.net.URI;

import com.oracle.coherence.environment.extensible.ConfigurationContext;
import com.oracle.coherence.environment.extensible.NamespaceContentHandler;

public class GreetingNamespaceContentHandler implements NamespaceContentHandler
{

    public void onStartScope(ConfigurationContext context,
                             String prefix,
                             URI uri)
    {
        // TODO Auto-generated method stub
    }


    public void onEndScope(ConfigurationContext context,
                           String prefix,
                           URI uri)
    {
        // TODO Auto-generated method stub
    }
}

As indicated by the above stub, the NamespaceContentHandler requires the implementation of two methods. These methods are call backs to notify your NamespaceContentHandler implementation when your namespace is first encountered (declared) and when it is no longer in scope (in the Cache Configuration file).
Both methods provide parameters for the underlying ConfigurationContext (handy for locating other "buddy" NamespaceContentHandlers, the prefix and the URI used to declare the namespace.

This is the minimal NamespaceContentHandler implementation.

To enable processing of XML element content, your NamespaceContentHandler additionally needs to implement the com.oracle.coherence.environment.extensible.ElementContentHandler interface. For example;

import java.net.URI;

import com.oracle.coherence.environment.extensible.ConfigurationContext;
import com.oracle.coherence.environment.extensible.ConfigurationException;
import com.oracle.coherence.environment.extensible.ElementContentHandler;
import com.oracle.coherence.environment.extensible.NamespaceContentHandler;
import com.oracle.coherence.environment.extensible.QualifiedName;
import com.tangosol.run.xml.XmlElement;

public class GreetingNamespaceContentHandler 
       implements NamespaceContentHandler, ElementContentHandler
{

    public void onStartScope(ConfigurationContext context,
                             String prefix,
                             URI uri)
    {
        // TODO Auto-generated method stub
    }


    public void onEndScope(ConfigurationContext context,
                           String prefix,
                           URI uri)
    {
        // TODO Auto-generated method stub
    }


    public Object onElement(ConfigurationContext context,
                            QualifiedName qualifiedName,
                            XmlElement xmlElement) throws ConfigurationException
    {
        // TODO Auto-generated method stub
        return null;
    }
}

As indicated by the above stub, the ElementContentHandler interface requires an implementation of the onElement method. This method is called by the ExtensibleEnvironment when it encounters each XML element in a Cache Configuration that belongs to your namespace.

The onElement method allows you to return a value to the parent XML onElement handler. If your ElementContentHandler does not produce a value for the parent XML element, simply return null

Let's now finish our GreetingNamespaceContentHandler.

import java.net.URI;

import com.oracle.coherence.environment.extensible.ConfigurationContext;
import com.oracle.coherence.environment.extensible.ConfigurationException;
import com.oracle.coherence.environment.extensible.ElementContentHandler;
import com.oracle.coherence.environment.extensible.NamespaceContentHandler;
import com.oracle.coherence.environment.extensible.QualifiedName;
import com.tangosol.run.xml.XmlElement;

public class GreetingNamespaceContentHandler 
       implements NamespaceContentHandler, ElementContentHandler
{

    public void onStartScope(ConfigurationContext context,
                             String prefix,
                             URI uri)
    {
        //not used in this implementation
    }


    public void onEndScope(ConfigurationContext context,
                           String prefix,
                           URI uri)
    {
        //not used in this implementation
    }


    public Object onElement(ConfigurationContext context,
                            QualifiedName qualifiedName,
                            XmlElement xmlElement) throws ConfigurationException
    {
        if (qualifiedName.getLocalName().equals("message"))
        {
            System.out.printf("Greeting is [%s]\n", xmlElement.getString());

            return null;
        }
        else
        {
            throw new RuntimeException("Unknown element type " + qualifiedName.getLocalName());
        }
    }
}

If your element contains child-elements that you'd like to have processed by the ExtensibleEnvironment, you must iterate over them individually and pass them to the ConfigurationContext processElement method for (recursive) processing. If the child-element produces a result, it will be returned to you from the processElement method.

Alternative Implementation

A possibly simpler approach to implementing a customer Namespace Content Handler is to inherit from the AbstractNamespaceContentHandler. By doing this you can take advantage of the ability to register individually named ElementContentHandlers and AttributeContentHandlers (typically created as Anonymous Inner Classes), thus avoiding the need to check the qualified name of elements passed to you in the onElement method.

import java.net.URI;

import com.oracle.coherence.environment.extensible.ConfigurationContext;
import com.oracle.coherence.environment.extensible.ConfigurationException;
import com.oracle.coherence.environment.extensible.ElementContentHandler;
import com.oracle.coherence.environment.extensible.QualifiedName;
import com.oracle.coherence.environment.extensible.namespaces.AbstractNamespaceContentHandler;
import com.tangosol.run.xml.XmlElement;

public class GreetingNamespaceContentHandler extends AbstractNamespaceContentHandler
{

    public void onStartScope(ConfigurationContext context,
                             String prefix,
                             URI uri)
    {
        registerContentHandler("message", new ElementContentHandler()
        {
            public Object onElement(ConfigurationContext context,
                                    QualifiedName qualifiedName,
                                    XmlElement xmlElement) throws ConfigurationException
            {
                System.out.printf("Greeting is [%s]\n", xmlElement.getString());

                return null;
            }
        });
    }
}