Tutorial Overview
|
Oracle Enterprise Gateway exposes several powerful APIs as part of its
Software Development Kit (SDK) to enable users to build their own bespoke
message filters. Users can leverage Oracle Enterprise Gateway's pluggable and
extensible architecture to enhance the message processing capabilities of
the Oracle Enterprise Gateway core processing engine.
This tutorial walks you through a step-by-step example of how to build a
custom-built message filter with the SDK, and integrate it into a policy.
This tutorial shows how to build the two main aspects of an Addition filter:
the server runtime component, and the Policy Studio configuration component.
It then integrates these components into a policy, and shows how the filter
adds the values of two parameters of a SOAP message together, and returns
the result to the client. By the end of this tutorial, you should be able
to write and test your own message filters by following a similar procedure.
Before going any further, however, it is important to explain exactly what
are Oracle Enterprise Gateway filters and to see exactly how they can be wired
together to create message processing policies.
|
Policies, Filters, and Message Attributes
|
A policy consists of a network of message filters where each filter is a
modular executable unit that performs a specific type of processing on a
message. The policy arranges these filters into sequences called paths.
The filters then act as decision-making points along these paths,
determining which filters are run on the message, and in what order.
The following four-node policy contains a single path
with four message filters. The filter marked as
Start (AuthN: WS-Security Username Token)
is executed first. If this filter runs successfully, the next filter in the
path (getQuotes Operation Name) is run, and so on until the
last filter (Echo Web Service) in the path is executed.
When an HTTP request is received, it is converted into a set of message
attributes. Each message attribute represents a specific characteristic
of the HTTP request, such as the HTTP headers, HTTP body, and MIME parts,
amongst others.
Every Filter declares the message attributes that it
requires, generates, and
consumes from the attributes blackboard.
The blackboard contains all the available message attributes. When a filter
generates message attributes it puts them up on the
blackboard so that when another Filter requires them
it can pull them off the blackboard. If a filter consumes
a message attribute, it is wiped from the blackboard so that no other filter
in the policy can use it.
The following table summarizes the attributes required and generated by
the Operation Name resolver, which filters incoming
requests based on their SOAP operation and namespace:
Filter Name: |
Operation Name |
Description: |
Filters incoming SOAP requests based on their SOAP
operation and namespace.
|
Required Attributes: |
content.body
http.request.uri
|
Generated Attributes: |
soap.request.method |
For more information on policy, policy building, filters, please refer
to your Enterprise Gateway documentation. The following list summarizes the
important concepts introduced in this section:
-
Policy:
A network of interconnected message filters.
-
Message Filters:
An executable unit that performs a specific type of processing on
message attributes.
-
Message Attributes:
Message attributes represent specific characteristics of a message.
|
Oracle Enterprise Gateway SDK Overview
|
The Oracle Enterprise Gateway Software Development Kit (SDK) comprises three Java
packages that provide programmatic access to Oracle Enterprise Gateway policies,
message objects, and the Entity Store. The following table describes these
packages:
Package |
Description |
com.vordel.circuit
|
This package is responsible for implementing the core Oracle
Enterprise Gateway policy. It includes the base classes for all message
filters and their associated classes.
|
com.vordel.mime
|
Includes classes that encapsulate the message as it passes through
the Oracle Enterprise Gateway policy. It also provides programmatic
access to HTTP headers, HTTP body, request query string (if present),
and MIME parts.
|
com.vordel.es
|
These classes provide access to the underlying Entity Store
where all configuration data is stored.
|
|
Tutorial Prerequisites
|
You should read Getting
Started to make sure you understand the concepts of policies and filters before
continuing.
The Oracle Enterprise Gateway SDK requires a JDK 1.6, and is supported for the Windows,
Linux, and Solaris packages.
|
Oracle Enterprise Gateway SDK Sample Overview
|
The Oracle Enterprise Gateway SDK ships with a working example of a message
filter, called the SimpleFilter , that demonstrates
how to use the SDK to build a filter. The filter extracts two integer
parameters from a SOAP message, adds the integers, and returns the
result of the addition in a SOAP response to the client.
This tutorial documents the steps required to build, integrate,
configure, and test the supplied SimpleFilter and
SimpleProcessor classes. The steps are as follows:
Step |
Description |
Step 1: Create TypeDocs
|
Every filter has an associated XML-based TypeDoc that contains
the entity's type definition. It defines the configuration
field names for that filter and their corresponding data types.
|
Step 2: Create Filter Class
|
Every message filter has an associated Filter class that
encapsulates the configuration data for a particular instance
of the filter. It also returns the corresponding Processor
and Policy Studio classes.
|
Step 3: Create Processor Class
|
The Processor class is the server runtime component that is
responsible for processing the message. Every message filter
has an associated Processor and Filter class.
|
Step 4: Create Policy Studio Classes
|
All Filters are configured using the Policy Studio. Every
Filter has a configuration wizard that enables you to set
each of the fields defined in the entity that corresponds to
that Filter. You can then add the filter to a policy to process
messages.
|
Step 5: Build Classes
|
When the classes have been written, they must be built and
added to the server and client classpaths.
|
Step 6: Load TypeDocs
|
The TypeDoc that is created for the filter in
Step 1 must be
registered with the Entity Store.
|
Step 7: Construct a Policy
|
This step constructs a policy that echoes messages back to the
client, and then adds the newly created filter to it.
|
Step 8: Configure the SimpleFilter
|
This step uses the GUI component of the newly added filter to
configure its configuration fields. It then tests the
functionality of the filter (and its configuration) using the
Oracle Service Explorer testing tool.
|
|
Step 1: Create the Typedocs
|
All configuration data is stored as entities in the Oracle Enterprise Gateway Entity
Store. The Entity Store is an XML-based store that holds all configuration
data required to run the Oracle core processing engine. Each configurable
item has an entity type definition. The entity type definition is defined in an
XML file known as the TypeDoc.
Entity types are analogous to class definitions in an object-oriented
programming language. In the same way that instances of a class can be
created in the form of objects, an instance of an entity type can also be
created. Therefore it is useful to think of the entity type defined in a
TypeDoc as a header file, and the entity itself as a class instance.
All entities and their entity type definitions are stored in the
Entity Store.
Every filter requires specific configuration data to perform its processing
on the message. For example, the SimpleFilter , which
extracts the values of two elements from a SOAP message, and adds them together,
must be primed with the names and namespaces of those two elements.
Because a filter is a configurable item, it requires a new XML typedoc to
be written containing an entity type definition for it. The entity type
for a filter contains a set of configuration parameters and their
associated data types and default values.
When an instance of the filter is added to a policy using the Policy Studio,
a corresponding entity instance is created and stored in the Entity Store.
Whenever the filter instance is invoked, its configuration data is read
from the entity instance in the Entity Store.
TypeDoc Syntax
The following example XML shows how the TypeDoc lists the various fields that
form the configuration data for the Filter.
| | |
|
<entityStoreData>
<entityType name="SimpleFilter" extends="Filter">
<!-- Name of filter class that encapsulates the config data -->
<constant name="class" type="string"
value="com.vordel.example.filter.SimpleFilter"/>
<!-- List of config fields, their types, and their default values -->
<field ... />
<field ... />
<field ... />
</entityType>
<entityStoreData>
| |
| | |
|
All TypeDocs must obey the following simple rules:
- Extend the Filter type
- Define a constant Filter class
- List the configuration fields for the entity
SimpleFilter Elements and Attributes
The following table describes the important elements and attributes
from the SimpleFilter TypeDoc listed above:
Element |
Attribute |
Description |
<entityStoreData> |
|
The topmost wrapper element for the entire type definition.
|
<entityType> |
|
Contains the type definition, including all its fields
and their types.
|
<entityType> |
name |
The unique name for this type.
|
<entityType> |
extends |
Entity definitions are hierarchical and can inherit from other
higher level types. All filters must extend
the Filter type.
|
<constant> |
|
A <constant> element is used to
represent a read-only immutable property of the type.
|
<constant> |
name |
This attribute contains the name of the read-only property.
In the example above, the named property is class ,
indicating that the value of this constant is the Java class
that encapsulates the defined type. The name of this class
must be specified as a <constant> .
|
<constant> |
type |
Specifies the type of the value attribute.
In this case, the value is the name of a Java class, which is
just a string.
|
<constant> |
value |
Contains the value of the named property, which is the name of
the Java class that encapsulates this type
(com.vordel.example.filter.SimpleFilter ).
|
<field> |
|
Contains the definition of a single configuration field for
this filter.
|
<field> |
name |
The name of the configuration field. You can see later in
this tutorial how this name is used to get and set this
property.
|
<field> |
type |
Specifies the data type of the named configuration field.
For example, supported types include string ,
boolean , encrypted , and integer .
|
<field> |
cardinality |
Stipulates how many times this field can appear in an instance
of the entity. For example, a cardinality of 1 means
that this field can only occur once within an entity.
|
<field> |
default |
Specifies a default value for the configuration field, if
appropriate.
|
SimpleFilter TypeDoc
The TypeDoc for the SimpleFilter is as follows:
| | |
|
<entityStoreData>
<entityType name="SimpleFilter" extends="Filter">
<!-- Name of Filter class that encapsulates this config entity -->
<constant name="class" type="string"
value="com.vordel.example.filter.SimpleFilter"/>
<!-- List of config params, their types, and their default values -->
<field name="param1" type="string" cardinality="1" default="a"/>
<field name="param1Namespace" type="string"
cardinality="1" default="http://startvbdotnet.com/web/"/>
<field name="param2" type="string" cardinality="1" default="b"/>
<field name="param2Namespace" type="string"
cardinality="1" default="http://startvbdotnet.com/web/"/>
</entityType>
</entityStoreData>
| |
| | |
|
All type and related information for the Filter is contained in the
top-level <entityStoreData> element. The
Filter type declaration together with its field definitions and types
are child elements of the <entityType>
element. Each field name is specified in the name
attribute of the <field> element, while the
type and default value for the field are specified in the
type and default attributes,
respectively.
You can also provide internationalized log messages by
specifying an <entity> block of type
InternationalizationFilter within
the <entityStoreData> elements.
Now that you understand how the configuration data for the filter is
defined, you can create the filter class.
|
Step 2: Create the Filter Class
|
A filter class encapsulates the type information defined in an entity's
type definition. There are class members that correspond to each
of the fields in the type definition. At runtime, when the filter is
invoked, the filter class is instantiated with the configuration data for
the appropriate entity instance. The filter class is responsible for the
following tasks:
-
Storing member variables corresponding to fields in the type
definition
-
Specifying the message attributes it requires, consumes, and
generates
-
Returning the corresponding server runtime class (the Processor)
-
Returning the corresponding Policy Studio class
SimpleFilter Class
The following code shows the members and methods of the
SimpleFilter.java example:
| | |
|
package com.vordel.example.filter;
import com.vordel.circuit.DefaultFilter;
import com.vordel.circuit.FilterConfigureContext;
import com.vordel.circuit.MessageProperties;
import com.vordel.es.EntityStoreException;
/**
SimpleFilter contains the local name of the two
parameters (a and b) and contains the namespace that
these elements belong to (http://startvbdotnet.com/web/)
**/
public class SimpleFilter extends DefaultFilter {
// element name of the first parameter
String param1;
// namespace of the first element
String param1Namespace;
// element name of the second parameter
String param2;
// namespace of the second parameter
String param2Namespace;
/**
* Set the message attributes used by this filter
*/
protected final void setDefaultProperties() {
requiredProperties.add(MessageProperties.CONTENT_BODY);
}
/**
* This method is called to set the config fields for the filter
* @param ctx The configuration context for this filter
* @param entity The entity object
*/
public void configure(FilterConfigureContext ctx,
com.vordel.es.Entity entity)
throws EntityStoreException {
super.configure(ctx, entity);
// read the settings for the processor
param1 = entity.getStringValue("param1");
param1Namespace = entity.getStringValue("param1Namespace");
param2 = entity.getStringValue("param2");
param2Namespace = entity.getStringValue("param2Namespace");
}
/**
* Returns the server runtime Processor class associated
* with this Filter class.
*/
public Class getMessageProcessorClass() {
return SimpleProcessor.class;
}
/**
* Returns the GUI component for this Filter
*/
public Class getConfigPanelClass() throws ClassNotFoundException {
// Avoid any compile or runtime dependencies on SWT and other UI
// libraries by lazily loading the class when required.
return
Class.forName("com.vordel.example.filter.simple.SimpleFilterUI");
}
}
| |
| | |
|
SimpleFilter TypeDoc
At this point, it is worth revisiting the entity definition for the
SimpleFilter entity to see how the class members
correlate to the defined fields.
| | |
|
<entityType name="SimpleFilter" extends="Filter">
<!-- Name of Filter class that encapsulates this config entity -->
<constant name="class" type="string"
value="com.vordel.example.filter.SimpleFilter"/>
<!-- List of config params, their types, and their default values -->
<field name="param1" type="string" cardinality="1" default="a"/>
<field name="param1Namespace" type="string"
cardinality="1" default="http://startvbdotnet.com/web/"/>
<field name="param2" type="string" cardinality="1" default="b"/>
<field name="param2Namespace" type="string"
cardinality="1" default="http://startvbdotnet.com/web/"/>
</entityType>
| |
| | |
|
SimpleFilter Methods
The Filter class members (param1 ,
param1Namespace , param2 ,
and param2Namespace ) directly correspond to the
field definitions in the type definition. These members are populated in
the configure method of the Filter class, which is
called by the framework when the server is started up initially, and whenever
the server is refreshed. The Entity class provides getter
and setter methods for the different data types (for example, string, boolean,
integer, and so on). For more details, see the
Entity Javadoc.
There are two more important methods implemented in this class:
setDefaultProperties and
getMessageProcessorClass . The
setDefaultProperties method enables the Filter to
define the message attributes that it requires,
generates, and consumes
from the attributes blackboard. The blackboard contains all the
available message attributes. When a filter generates
message attributes, it puts them up on the blackboard so that when another
Filter requires them, it can pull them off the
blackboard. If a filter consumes a message
attribute, it is wiped from the blackboard so that no other filter in the
policy can use it.
The attributes are stored in String arrays (reqProps ,
genProps , conProps ), which are
inherited from the VariablePropertiesFilter class.
In the case of the SimpleFilter class, the
content.body attribute is required because the SOAP
parameters must be extracted from the body of the HTTP request.
The next important method here is the getMessageProcessorClass
method, which returns the server runtime component (the Processor class) that is
associated with this Filter class. Each Filter class has a corresponding Processor
class, which is responsible for using the configuration data stored in the Filter
class to process the message. The next step looks at the
SimpleProcessor class to see how it acts on the data stored
in the SimpleFilter class.
Finally, the corresponding Policy Studio configuration class is returned by
the getConfigPanelClass method, which in this case
is the
com.vordel.example.filter.simple.SimpleFilterUI
class. This class is described in detail in
Step 4 of this tutorial.
|
Step 3: Create Processor Class
|
The Processor class is responsible for performing the processing on the
message. It uses the configuration data stored in the Filter class to
determine how to process the message. It is important to note that this
is the server runtime component of the filter that is returned by the
getMessageProcessorClass of the Filter class
described in the previous section.
Example Skeleton Code
The following skeleton code shows how the Processor attaches
to the Filter class and uses its data to process the message. The following code
is for illustration purposes only, and some of the SimpleProcessor
code has been omitted.
| | |
|
package com.vordel.example.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.vordel.circuit.Circuit;
import com.vordel.circuit.CircuitAbortException;
import com.vordel.circuit.Filter;
import com.vordel.circuit.Message;
import com.vordel.circuit.MessageProcessor;
import com.vordel.circuit.MessageProperties;
import com.vordel.es.EntityStore;
import com.vordel.mime.Body;
import com.vordel.mime.ContentType;
import com.vordel.mime.HeaderSet;
import com.vordel.mime.XMLBody;
import com.vordel.trace.Trace;
/**
* This Processor acts as a simple Addition Web Service.
* It extracts two parameters from a SOAP message and adds them together.
* The result is then returned to the client.
* The incoming message is expected in the following format:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://startvbdotnet.com/web/">
<a>1</a>
<b>1</b>
</Add>
</soap:Body>
</soap:Envelope>
The SimpleFilter contains the local name of the two parameters (a
and b ), and contains the namespace that these elements belong to
(http://startvbdotnet.com/web/ ).
*/
public class SimpleProcessor extends MessageProcessor {
/**
* This method attaches the Filter to the Processor object.
* This is called at startup and on every refresh.
* This should contain server-side config/initialization.
* For example, if this filter is required to establish
* connections to any 3rd party products/servers, the
* connection setup should be done here.
* @param ctx Configuration context for the filter.
* @param entity The Entity object
*/
public void filterAttached(FilterConfigureContext ctx,
com.vordel.es.Entity entity)
throws EntityStoreException {
// nothing to do here for initialisation
super.filterAttached(ctx, entity);
}
/**
* The invoke method performs the filter processing.
* @param c The circuit
* @param message The message
* @return true or false.
*/
public boolean invoke(Circuit c, Message message)
throws CircuitAbortException {
try {
// Get the incoming request message as a DOM
Document doc = getDOM(message);
// Default result
String result = "UNKNOWN";
// Cast the filter member variable to a SimpleFilter so that
// you may access the values stored in the SimpleFilter's
// fields (for example, param1, param1Namespace, and so on).
SimpleFilter f = (SimpleFilter)filter;
// Look into the DOM to get the two parameters.
// Get the 1st parameter
NodeList param1 =
doc.getElementsByTagNameNS(f.param1Namespace, f.param1);
if (param1 == null || param1.getLength() <= 0)
throw new CircuitAbortException(
"Could not find " + f.param1 + "in message");
// Get the value passed in the 1st parameter
String a = getElementContent((Element)param1.item(0));
// Get the 2nd parameter
NodeList param2 =
doc.getElementsByTagNameNS(f.param2Namespace, f.param2);
if (param2 == null || param2.getLength() <= 0)
throw new CircuitAbortException(
"Could not find " + f.param2 + "in message");
// Get the value of the 2nd parameter
String b = getElementContent((Element)param2.item(0));
// Calculate the result by adding the two parameter values
result =
Integer.toString(Integer.parseInt(a) + Integer.parseInt(b));
// Set the response by setting the content body
// to be the response
HeaderSet responseHeaders = new HeaderSet();
responseHeaders.putString("Content-Type", "text/xml");
StringBuffer response = new StringBuffer(RESPONSE_START);
response.append(result);
response.append(RESPONSE_END);
Body convertedBody =
Body.create(responseHeaders, new ContentType("text/xml"),
new ByteArrayInputStream(
response.toString().getBytes()));
message.setProperty(
MessageProperties.CONTENT_BODY, convertedBody);
return true;
}
catch (IOException exp) {
Trace.error("IOException in SimpleProcessor: " + exp.getMessage());
return false;
}
}
}
| |
| | |
|
Processor Methods
There are two important methods that must be implemented by every
Processor: the filterAttached method and the
invoke method. The
filterAttached method associates an appropriate
Filter class with the Processor. The Processor can then access the
configuration data stored in the Filter class. In this case, the
SimpleProcessor attaches to the
SimpleFilter class. The
filterAttached method should contain any server-side
initialization or configuration that is to be performed by the Filter,
such as connecting to third-party products or servers.
The invoke method is responsible for using the data
stored in the attached Filter class to perform the message processing.
This method is called by the server as it executes the series
of filters in any given policy. In the case of the
SimpleFilter , the invoke
method extracts the values of the <a> and
<b> elements from the SOAP message, and adds
the two values together. The result is then returned to the client in a
templated SOAP response.
It is important to note that the invoke method can
have the following possible results:
Result |
Description |
True |
If the filter processed the message successfully (for example,
successful authentication, schema validation passed, and so on),
the invoke method should return a true result,
meaning that the next filter on the success path for the filter is
invoked.
|
False |
If the filter's processing fails (for example, the user was not
authenticated, message failed integrity check, and so on), the
invoke method should return false,
meaning that the next filter on the failure path for the
filter is invoked.
|
CircuitAbortException |
If for some reason the filter cannot process the message
at all (for example, if it can not connect to an Identity
Management server to authenticate a user), it should
throw a CircuitAbortException . If a
CircuitAbortException is thrown in a policy,
the designated Fault Processor (if any) is invoked instead
of any successive filters on either the success or failure paths.
|
Now that you have a class to encapsulate the configuration data and
another class to act on that data, it is now time to create some GUI
classes where the user can configure the fields stored in the Filter
class.
|
Step 4: Create Policy Studio Classes
|
The next step involves writing two GUI classes so that the fields defined
in the SimpleFilter type definition can be
configured. When the GUI classes and resources have been built, the
visual components can be used in the Policy Studio to configure the Filter
and add it to a policy.
SimpleFilter GUI Classes and Resources
The following table describes the GUI classes and resources that relate to
the SimpleFilter :
Class or Resource |
Description |
SimpleFilterUI.java |
This class is used to list the pages that are involved
in a Filter's configuration screen. Each Filter has at
least two pages: the main configuration page, and a page
where log messages related to the filter can be customized.
This class is returned by the
getConfigPanelClass method of the
SimpleFilter class.
|
SimpleFilterPage.java |
This class defines the layout of the visual fields on the
Filter's main configuration screen. For example, there are
four text fields on the configuration screen for the
SimpleFilter corresponding to the four
fields defined in the entity's type definition.
|
resources.properties |
This file contains all text that is displayed in the GUI
configuration screen (for example, dialog titles, field names,
and error messages). This means that the text can be customized
or internationalized easily without the need for code change.
|
simple.gif |
This image file is used as the icon to identify the Filter in
the Management Console, and is displayed in the Filter Palette.
|
This step first looks at the SimpleFilterUI class,
which is returned by the getConfigPanelClass method
of the SimpleFilter class. It is responsible for
the following:
-
Listing the configuration pages that make up the interface for
the filter
-
Naming the category of filters to which this filter belongs
-
Specifying the name of the images to use as the icons/images for
this filter
SimpleFilterUI Class
The code for the SimpleFilterUI is as follows:
| | |
|
package com.vordel.example.filter.simple;
import java.util.Vector;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import com.vordel.client.manager.Images;
import com.vordel.client.manager.filter.DefaultGUIFilter;
import com.vordel.client.manager.wizard.VordelPage;
/**
* Filter configuration GUI for 'Simple' example filter.
* This class shows how to code simple text fields for configuring a
* custom filter.
*/
public class SimpleFilterUI
extends DefaultGUIFilter
{
/**
* Add the pages you want to show in the configuration wizard for the filter.
*/
public Vector<VordelPage> getPropertyPages() {
Vector<VordelPage> pages = new Vector<VordelPage>();
// Add the panel for configuring the specific fields
pages.add(new SimpleFilterPage());
// Add the page which allows the user to set the log strings for the
// audit trail, for the pass/fail/error cases
pages.add(createLogPage());
return pages;
}
/**
* Set the categories in which you want to display this Filter. The
* categories define the sections of the palette in which the Filter
* appears. The values returned should be the localized name of the
* palette section, so ensure that the property is defined in the
* resources.properties in this class' package. You will add this
* file to the "Example Filters" category.
*/
public String[] getCategories() {
return new String[]{_("FILTER_GROUP_EXAMPLE")};
}
/*
* Register our custom images with the image registry
*/
private static final String IMAGE_KEY = "simpleFilter";
static {
Images.getImageRegistry().put(IMAGE_KEY,
Images.createDescriptor(SimpleFilterUI.class, "simple.gif"));
}
/**
* The icon image needs to be added in images.properties in com.vordel.client.manager
* the id used there is used as a reference here.
* Use this method to get image id for the small icon image in Images.get(id), etc.
*/
public String getSmallIconId() {
return IMAGE_KEY;
}
/**
* Implement this method if you want to display a non-default image
* for your filter in the circuit editor canvas and navigation tree.
*/
public Image getSmallImage() {
return Images.get(IMAGE_KEY);
}
/**
* Implement this method to display a non-default icon for your filter in
* the palette.
*/
public ImageDescriptor getSmallIcon() {
return Images.getImageDescriptor(IMAGE_KEY);
}
}
| |
| | |
|
SimpleFilterUI Methods
The following table describes the important methods:
Method |
Description |
public Vector getPropertyPages() |
Initializes a Vector of the Pages that makeup the total
configuration screens for this Filter. Successive Pages are
accessible by clicking the Next button on the
Policy Studio configuration screen.
|
public String[] getCategories() |
This method returns the names of the Filter categories that this
Filter belongs to. The Filter is displayed under these categories
in the Filter Palette in the Policy Studio. The
SimpleFilter is added to the Example
Filters category.
|
public Image getSmallImage() |
The default image for the Filter, which is registered in the
static block in the code above, can be overridden by returning a
different image here.
|
public ImageDescriptor getSmallIcon() |
The default icon for the Filter can be overridden by returning a
different icon here.
|
A Page only represents a single configuration screen
in the Policy Studio. You can chain together several Pages to form a series
of configuration screens that together make up the overall configuration for
a given Filter. By default, all Filters consist of two pages: one for the
configuration fields for the Filter, and the other to allow per-Filter logging.
However, there is no reason why more Pages can not be chained together.
Successive Pages should be added to the configuration in the
getPropertyPages method.
From looking at the getPropertyPages method of the
SimpleFilterUI , it is clear that the
SimpleFilterPage class forms one of the
configuration screens (or pages) for the SimpleFilter
filter. The SimpleFilterPage class is responsible for
the layout of all the input fields that make up the configuration screen for
the SimpleFilter .
SimpleFilterPage Class
The code for the SimpleFilterPage class is shown below:
| | |
|
package com.vordel.example.filter.simple;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import com.vordel.client.manager.wizard.VordelPage;
public class SimpleFilterPage extends VordelPage
{
/**
* Create the configuration page. Set the title and description
* here. The title and description are maintained in the
* resources.properties file for customization and
* internationalization purposes.
*/
public SimpleFilterPage() {
// Call the super constructor with a unique name for this
// page to bind it with its corresponding wizard.
super("simplePage");
setTitle(_("SIMPLE_PAGE"));
setDescription(_("SIMPLE_PAGE_DESCRIPTION"));
setPageComplete(false);
}
/**
* Get the unique identifier for the help page for this filter.
* The id-to-page mapping is maintained in the
* '/docs/res/help.jhm' file. The URL for the page to describe
* the filter should be relative to the '/docs' directory.
*/
public String getHelpID() {
return "simple.help";
}
/**
* Any post-processing of the configuration values can happen
* here, before they are persisted to the Entity Store. If the
* configuration is not complete and valid, notify the user here
* with a dialog box and return false here, otherwise return true.
*
* @see com.vordel.client.manager.util.MsgBox
*/
public boolean performFinish() {
// Simple mutually independent values here, no checking required,
// so return true
return true;
}
/**
* Create the main control for the Filter configuration dialog.
* This will house the text fields for setting the particular
* Field Values in the Entity.
*/
public void createControl(Composite parent) {
// Create a Panel with two columns
GridLayout layout = new GridLayout();
layout.numColumns = 2;
Composite container = new Composite(parent, SWT.NULL);
container.setLayout(layout);
// Add controls to populate the appropriate Entity Fields
// You use the localization keys for the field names and
// descriptions which will map to entries in the
// resources.properties file.
createLabel(container, "SF_NAME");
createTextAttribute(container, "name", "SF_NAME_DESC");
createLabel(container, "SF_PARAM1");
createTextAttribute(container, "param1", "SF_PARAM1_DESC");
createLabel(container, "SF_PARAM1NS");
createTextAttribute(container, "param1Namespace", "SF_PARAM1NS_DESC");
createLabel(container, "SF_PARAM2");
createTextAttribute(container, "param2", "SF_PARAM2_DESC");
createLabel(container, "SF_PARAM2NS");
createTextAttribute(container, "param2Namespace", "SF_PARAM2NS_DESC");
// Finish up the page definition
setControl(container);
setPageComplete(true);
}
}
| |
| | |
|
SimpleFilterPage Methods
There are four important interface methods that must be implemented in
this class:
Method |
Description |
public SimpleFilterPage() |
The constructor performs some basic initialization, such as
setting a unique ID for the page and setting the title and
description for the page. The text representing the page
title and description are kept in the
resources.properties file so that they
can be localized or customized easily, if necessary.
|
public String getHelpID() |
This method is called by the Policy Studio help system. There is
a Help button on every configuration page in
the Policy Studio. When this button is pressed, the help system
is invoked. Every page has a help ID (for example,
simple.help ) associated with it, which is mapped to
a help page. This mapping is defined in the
/plugins/com.vordel.rcp.policystudio.resources_(version ...)/contexts.xml
file under the directory where you have installed Policy Studio,
for example:
| | |
|
<context id="simple_help">
<description>>Simple filter test</description>
<topic label="Simple Filter" href="html/common/tutorials/general_filter.html"/>
</context>
| |
| | |
|
Please note a dot in a help ID is replaced by underscore
in the contexts.xml file as in the example above.
All URLs specified in the contexts.xml file
are relative from the
/plugins/com.vordel.rcp.policystudio.resources_(version ...)
folder of your Policy Studio installation. You can add the lines
from the example above to the contexts.xml
file now, and you will check that the help page works at the
end of this tutorial.
|
public boolean performFinish() |
This method gives you the chance to process the user-specified
data before it is submitted to the Entity Store. For example,
any validation on the data should be added to this method.
|
public void createControl(Composite parent) |
This method is responsible for creating and ordering the input
fields on the configuration page. Again, localization keys from
the resource.properties file are used to
give labels for the input fields. It is important to
note that the createTextAttribute takes a
String as its second parameter, which corresponds to a field
defined for an entity (for example, param ,
param1Namespace , param2 , and
param2Namespace are all defined in the
SimpleFilter entity type. When the user
submits the values entered in these fields, the values are
set to the corresponding fields in the entity instance in the
Entity Store.
|
resources.properties File
Both the SimpleFilterUI and the
SimpleFilterPage classes use localized keys for all
text that is displayed on the configuration screen. This makes it a trivial
task to localize or customize all text that is displayed in the Policy Studio.
The localization keys and their corresponding strings are stored in the
resources.properties file, which takes the following
format:
| | |
|
# Palette category for example filters
FILTER_GROUP_EXAMPLE=Example Filters
# Title and Description for the SimpleFilter
SIMPLE_PAGE=Simple Filter Configuration
SIMPLE_PAGE_DESCRIPTION=Configure parameter values for the Simple Filter
#
# Field labels and descriptions
#
SF_NAME=Filter Name:
SF_NAME_DESC=The name of the Simple Filter
SF_PARAM1=Parameter 1
SF_PARAM1_DESC=the first parameter
SF_PARAM1NS=Parameter 1 Namespace
SF_PARAM1NS_DESC=the first parameter namespace field
SF_PARAM2=Parameter 2
SF_PARAM2_DESC=the second parameter
SF_PARAM2NS=Parameter 2 Namespace
SF_PARAM2NS_DESC=the second parameter namespace field
| |
| | |
|
The final resource is the simple.gif image file,
which is displayed as the icon for the SimpleFilter in
the Policy Studio. You can see this icon a little later in this tutorial
when you configure the SimpleFilter .
Now that all classes and resources have been written, it is now time to
build the relevant JAR files and incorporate them into the product.
|
Step 5: Build Classes
|
You must perform the following steps to build the
Java classes and resources described in the previous sections.
Important Note:
The classes must be built against a 1.6 JDK because this is used to build the
Enterprise Gateway, which contains the JAR files for the Enterprise Gateway SDK API.
-
Build the classes and associated resources into a JAR file using your
chosen build technology.
-
Place the new JAR in the
GW_HOME/ext/lib directory,
where GW_HOME refers to the root of your Enterprise Gateway
installation.
-
In the Policy Studio main menu, select Window ->
Preferences -> Runtime Dependencies,
and click Add to browse to the new JAR, and add it to the
list (for example,
GW_HOME/ext/lib/VordelExampleFilters.jar ).
-
Place any third-party JAR files used by your classes into the
GW_HOME/ext/lib , and add them to the list of
Runtime Dependencies in the Policy Studio.
-
Restart both the server and the Policy Studio.
For an example of building the SimpleFilter
classes, see the Ant build.xml file supplied
in the SDK_HOME/example/filter/src directory,
where SDK_HOME points to the root of your
SDK installation.
The Ant file builds the SimpleFilter classes
and packages all associated resources into the
VordelExampleFilters.jar file. You must then
place this file into the GW_HOME/ext/lib folder,
and add it to the Runtime Dependencies in the
Policy Studio Preferences.
When both the server and the Policy Studio boot up, they automatically
pick up the new JAR file. In the remaining steps of this tutorial, you
can see how to configure a policy that includes the
SimpleFilter and then test its functionality.
|
Step 6: Load TypeDocs
|
You must now register the type definition for the SimpleFilter
with the Entity Store using the Policy Studio. When the entity type has been registered,
it is guaranteed that any time the server needs to create an instance of the
SimpleFilter , the instance contains the correct fields with the
appropriate types.
Register using the Policy Studio
To register the type definition sing the Policy Studio, perform the following steps:
-
Start the Policy Studio and connect to the Enterprise Gateway. The following screen is displayed:
-
Select Window -> Show View -> Profile
Repository from the main menu, and you should see a screen similar
to the following:
-
Create a copy of the active configuration. To do this, expand the
Core Configurations tree node, and right-click the
active configuration (for example, Default Configuration).
Select Create via Copy in the context menu, and give the new
configuration a meaningful name (for example,
Custom Filter Config ).
-
Right-click the new configuration, and select Edit from the context menu.
You are asked to enter a passphrase. If this has not been changed from the default,
you can leave the field blank and proceed. This displays the Profile Editor
tab with Custom Filter Config as a root node. Right-click this root node,
and select Import Custom Filter Types from the menu.
-
Browse to the location of the
sampleTypeSet.xml
file, which is located in the /filter directory of
your Oracle Enterprise Gateway installation. A TypeSet
file is used to group together one or more TypeDocs so that multiple TypeDocs
can be added to the Entity Store in batch mode. The
sampleTypeSet.xml file is displayed as follows:
| | |
|
<typeSet>
<!-- SimpleFilter TypeDoc -->
<typedoc file="SimpleFilter.xml"/>
</typeSet>
| |
| | |
|
-
After selecting the TypeSet, the workspace refreshes. To verify that
the filter is available, navigate to a pre-existing policy, and you should
see the Example Filters category in the palette,
with the filters contained inside.
-
Right click the configuration, and commit this version. From now on, any
further revisions of this version, or configurations copied from this
configuration contain the new filter types.
-
Click the Deployment Details tab on the Dashboard,
and select the running process and the core configuration. You can
now deploy the new
Custom Filter Config with the latest
version containing the new types.
-
Click the Deploy button at the bottom right of the screen.
Verifying using the Entity Explorer
Another way to verify that your new filter has been installed is to use the
Entity Explorer. You can use the Entity Explorer
tool for browsing the entity types and entity instances that have been registered
with the Entity Store.
To verify that the filter has been installed, perform the following steps:
-
Start the Entity Explorer from the
/bin directory of your
installation using the esexplorer startup script. The
Entity Explorer is displayed as follows:
There are two main tabs on the Entity Store's interface: Entities
and Types. The Types tab lists all currently
defined entity types that have been registered with the Entity Store, while the
Entities tab lists all the instances of entities that have been
committed to the Entity Store (for example, configured filters).
-
You must first point the Entity Explorer at the management interface exposed by a
running instance of the Enterprise Gateway. Right-click the Entity Stores
node in the Entity Hierarchy tree:
Connecting to an Entity Store
|
The Connect to an Entity Store dialog is displayed as
follows:
Connect to an Entity Store
|
-
The Enterprise Gateway exposes a management service that interfaces to the underlying
Entity Store. This is the preferred method of managing the Entity Store. You can
now start the Enterprise Gateway (which connects to the Entity Store), and point the
Entity Explorer at the management service exposed by the Enterprise Gateway. Start the
Enterprise Gateway from the
/bin directory of your product installation.
-
You can now configure the Entity Explorer to talk to the management service exposed
by the Enterprise Gateway. By default, this service is available at the following URL, where
HOST refers to the host name or IP address of the machine on which the
Enterprise Gateway is running:
http://HOST:8090/configuration/policies .
-
Enter this address in the URL field of the Connect to an
Entity Store dialog. If you have not already changed the default username
and password for the entity store, use the default username
admin with
password changeme . Otherwise, specify the alternative username and
password in the fields provided. Click OK to connect to the management
service on the Enterprise Gateway. A log message is displayed in the Log panel at the bottom
right corner of the screen to confirm that you are connected to the Enterprise Gateway at the
specified URL.
-
Expand the Entity Store filename, and then expand the System Components
node to display the list of entity instances stored in the Entity Store:
Instances of Entities Stored in the Entity Store
|
-
Click the Types tab, expand the node representing
the Enterprise Gateway's management interface, (for example,
http://my_host:8090/configuration/policies ),
and expand the Entity node to display the list of
registered entity types. Each of these entity types has a corresponding
type definition. Expand the Filter node, and click the
SimpleFilter entity type in the tree. The names and
data types of the fields for this entity type can be seen under the
Details tab on the right of the Entity Explorer. To
view the type definition for this entity, click the XML tab.
These details should match the filter that has just been added.
SimpleFilter Loaded in the Entity Store
|
The Entity Store is now aware of the SimpleFilter
type. You can now create an instance of a Filter class that encapsulates
the fields defined in the SimpleFilter type.
The remaining steps in this tutorial show how to configure a policy that
includes the SimpleFilter , and then tests its functionality.
|
Step 7: Construct a Policy
|
This section first shows how to build a simple policy that echoes messages
back to the client. The next step then adds the SimpleFilter
to the policy.
You can build policies using the Policy Editor in the Policy Studio.
To build a policy, you can drag message filters from the filters palette on the
left on to the policy canvas on the right. You can then link these filters using
success or failure paths to create a
network of filters. The following screenshot shows the Policy Editor screen:
The policy canvas is the large blank area on the screen, while the filters
palette is the area on the right that contains the filters. Message filters
are grouped together by category (for example, all the content-based filters
are displayed together in one group, while all the authentication filters are
displayed in a different group). You can build policies by dragging these
filters and dropping them on to the canvas.
Important Note:
If you have followed the steps outlined above, you can see a new category of
filters named Example Filters in the filter palette. The
Example Filters category is expanded in the example screenshot.
Creating the Policy
To create a policy, perform the following steps:
-
Right-click Policies in the tree
view to the left of the Policy Studio, and select Add Policy.
Enter Circuit 1 as the name of the new policy in the
Policy dialog.
-
This example creates a policy containing only one filter: the
Reflect filter. This filter simply echoes the client
message back to the client. The Reflect filter is found
in the Utility filter group. Drag this filter on to the
editor.
-
Enter a name for the filter (or use the default) in the field provided.
Select the default value (
200 ) for the HTTP
response status code, and click Finish. The policy
needs to have a start filter, so right-click the Reflect filter,
and choose Set as Start.
-
You must now configure the Process to invoke the new policy. On the
Services tab in Policy Studio, select the Process (for example
Enterprise Gateway) -> Default Services. Right-click
Path: /, and select Edit.
-
Enter the following values on the
Configure Relative Path dialog:
-
Relative Path:
Keep / in this field, meaning that the Process invokes
the policy selected below for all requests received on this path.
-
Policy:
Select Circuit 1 to configure the server to send all
requests received on the path configured above to our newly configured policy.
-
To force the server to pick up the new configuration, you must deploy
the configuration to the server. Click the Deploy or press F6.
-
To test this, start up the Service Explorer testing tool
(distributed separately):
-
Assuming your HTTP interface is listening on port 8080, you can configure
Service Explorer to send a request to:
http://HOST:8080/ , where HOST is
the hostname or IP address of the machine on which the server is running.
Note that you send to / because, earlier, you
configured the firewall to filter requests received on this relative path.
-
Copy any SOAP message into the Request panel of
Service Explorer. Click the triangular green Send
button to send the message to the server, which echoes it back to the
client using the Reflect filter configured earlier.
When the message has been returned to Service Explorer, try
changing the message slightly to assure yourself that the correct message
is actually being returned.
Finally, it is time to add the SimpleFilter to the
policy, and to test its functionality.
|
Step 8: Configure the SimpleFilter
|
The final section of this tutorial adds the SimpleFilter
to the policy built in the previous section. Currently, the policy consists of
only one filter, the Reflect filter:
The SimpleFilter is found in the Example
Filters category of the Filter Palette on
the Policy Studio.
Configuring the Filter
To configure the new filter, perform the following steps:
-
Drag and drop the SimpleFilter on to the policy canvas.
The configuration screen is displayed as follows:
-
Because the type definition for the
SimpleFilter
entity contained default values, the input fields on the configuration
screen are pre-populated with these default values.
-
Before completing the configuration, make sure the help system is working
correctly. Remember that in Step 4
of this tutorial, you added a mapping to the
contexts.xml
file (in the
/plugins/com.vordel.rcp.policystudio.resources_(version ...)
folder of your Policy Studio installation.) If you have not done so yet,
this is explained in Step 4.
After restarting Policy Studio, you can try clicking the Help
button while editing the SimpleFilter configuration.
-
Right-click the Simple node, and select Set as
Start from the context menu. Connect the Simple
node to the Reflect node with a success
path. You can do this by clicking the Success Path arrow,
and then clicking the Simple node, followed by clicking
the Reflect node. The policy is now displayed as follows:
Policy with SimpleFilter and Reflect
|
-
To force the server to pick up the new configuration, you must refresh
the server. Click the Deploy button in
Policy Studio (or press F6).
-
You can now test the configuration to make sure that it performs as
expected (that it can correctly add the two numbers together). Load the
appropriate SOAP message into the Service Explorer by
selecting the File -> Samples -> Add two numbers
menu option. The following SOAP message is loaded:
| | |
|
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://startvbdotnet.com/web/">
<a>1</a>
<b>2</b>
</Add>
</soap:Body>
</soap:Envelope>
| |
| | |
|
Important Note:
Note the presence of the <a> and
<b> elements in the SOAP message, and the
namespace declaration in the <Add> element.
These elements and their corresponding namespaces match the values
configured in the SimpleFilter earlier.
Make sure to send the message to the same address as before by entering
http://localhost:8080/ as the URL. The
Wsdl field is not needed and can be removed.
Press the Run (Send) button when you have done
this to send the message to the server.
The following response is returned to Service Explorer:
| | |
|
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AddResponse xmlns="http://startvbdotnet.com/web/">
<AddResult>3</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
| |
| | |
|
The value of the <AddResult> element is
3 , which indicates that the newly added filter
has worked successfully.
|
Conclusion
|
This tutorial described a working example of how to write a message
processing filter using the Oracle Enterprise Gateway and how to integrate it
into a policy. You should now try to build your own filter by
following a similar sequence of steps to those outlined in this tutorial.
If you have any queries on the content of this document, please contact
the Support Team with your
questions.
|
|