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>
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 XMLonElement
handler. If yourElementContentHandler
does not produce a value for the parent XML element, simply returnnull
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 theConfigurationContext
processElement
method for (recursive) processing. If the child-element produces a result, it will be returned to you from theprocessElement
method.
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;
}
});
}
}