These interfaces provide full support for the mediation primitive programming model. The mediation primitive programming model allows the development of mediation primitives which can then be composed into mediation flows.
Mediation primitives are the building blocks of mediation flows. A mediation primitive may be thought of as a piece of logic which acts on a message as it passed along a mediation flow. It may modify the contents of the message, and may also route the message by firing its output terminals.
A mediation primitive may have one or more input terminals, and zero or more output terminals. In addition, they also have zero or one failure terminals which are not exposed to the primitive programmer.
Mediation primitives are realized as Java beans which implement the SPI described by the Javadoc. The basic interface of a mediation primitive is described by the {@link com.ibm.wsspi.sibx.mediation.Mediation Mediation} interface. This defines the methods which must be implemented by mediation primitive programmers.
Messages arrive at input terminals, and are processed by the primitive logic. As a result of the logic, the primitive may fire zero or more of its output terminals. The terminals of primitives are wired together to produce mediation flows.
If a mediation primitive encounters any problems during the mediation of a message, it may throw either a {@link com.ibm.wsspi.sibx.mediation.MediationConfigurationException MediationConfigurationException} or a {@link com.ibm.wsspi.sibx.mediation.MediationBusinessException MediationBusinessException} to indicate the fact. This will result in the invocation of the primitive's failure terminal.A default implementation of Mediation is provided in the {@link com.ibm.wsspi.sibx.mediation.AbstractMediation AbstractMediation} class. This implements the {@link com.ibm.wsspi.sibx.mediation.Mediation#setMediationServices(com.ibm.wsspi.sibx.mediation.MediationServices) setMediationServices} method, a useful {@link com.ibm.wsspi.sibx.mediation.AbstractMediation#getMediationServices() getMediationServices} method and also provides a default implementation of the {@link com.ibm.wsspi.sibx.mediation.Mediation#init() init} method.
A mediation primitive can access meta-data about itself via a {@link com.ibm.wsspi.sibx.mediation.MediationServices MediationServices} interface. This provides access to the input and output terminals, as well as the name of the primitive (as it is known within the flow) and its display name (which is normally more meaningful to an end user.)
The input and output terminals retrieved from the MediationServices are derived from the {@link com.ibm.wsspi.sibx.mediation.Terminal Terminal} interface. This interface provides access to the name of the terminals, as well as the {@link com.ibm.wsspi.sibx.mediation.TerminalType TerminalType.}
Input terminals are described by the {@link com.ibm.wsspi.sibx.mediation.InputTerminal InputTerminal} interface, whilst output terminals are described by the {@link com.ibm.wsspi.sibx.mediation.OutputTerminal OutputTerminal} interface. The OutputTerminal interface provides an additional {@link com.ibm.wsspi.sibx.mediation.OutputTerminal#fire(DataObject) fire} method which allows a mediation primitive to fire an output terminal.
Mediation primitives can define various properties which the mediation flow engine will populate from configuration information during the creation of the mediation primitive. These properties are defined by using the standard Javabean mechanisms. Namely, each property must have a public getter and setter method. Indexed properties are permitted.
6.0.2 onwards
From WebSphere ESB 6.0.2, it is possible for the properties of mediation primitives
to be externally modified by administrators. There are scenarios where the internal
value of a mediation primitive property is different to the value seen by, and
expected to be set by the administrator. A typical example is where where the value
of the property is presented as a choice from a restricted set of values. These may
be presented to the administrator as string literal values such as "All" or "First"
but may internally be recognised as integers such as 0 or 1.
In this case, the mediation primitive must provide an additional method to perform
any conversion from the string literal form to the form expected by the primitive. The
signature of this method must be:
publicConvert(String stringForm);
For example, you may implement a mediation primitive with an integer property whose string literal values may be "First" and "All" in such a way:
public static class FooMediation implements Mediation { private int distributionMode; private static final String MODE_FIRST = "first"; private static final String MODE_ALL = "all; public int getDistributionMode() { return distributionMode;} public void setDistributionMode(int distributionMode) { this.distributionMode = distributionMode; } public int distributionModeConvert(String modeString) { int result = -1; try { result = Integer.parseInt(modeString); } catch (NumberFormatException nfe){ if(modeString.equalsIgnoreCase(MODE_FIRST)) { result = 0; } else if (modeString.equalsIgnoreCase(MODE_ALL)) { result = 1; } } return result; } ... }
The mediation engine will always look for a conversion method before calling the setter for a mediation primitive property. If no conversion method is specified then the engine will attempt to convert the String directly to the expected type of the property.
A mediation primitive has the following lifecycle:
The simplest way to program a mediation primitive is to extend the
AbstractMediation
class, and implement the mediate
method:
public class FooMediation extends AbstractMediation { public void mediate(InputTerminal inputTerminal, DataObject message} throws MediationConfigurationException, MediationBusinessException { // Do something with the message } }
However, we will want to obtain the terminals for the mediation
primitive, both to validate they are what we expect, and to fire
output terminals later on. The best way to do this is to override the
init
method:
public class FooMediation extends AbstractMediation { private InputTerminal in; private OutputTerminal out; public void init() throws MediationConfigurationException { in = getMediationServices().getInputTerminal("in"); if(in == null) { throw new MediationConfigurationException("No input terminal named in"); } out = getMediationServices().getOutputTerminal("out"); if(out == null) { throw new MediationConfigurationException("No output terminal named out"); } } public void mediate(InputTerminal inputTerminal, DataObject message} throws MediationConfigurationException, MediationBusinessException { // Do something with the message } }
In addition, we may want to provide some configuration to our mediation
primitive by implementing some properties. For instance, we may want to
define a string property named bar
. We can also check that the
value of that property is correct in the init
method:
public class FooMediation extends AbstractMediation { private String bar; private InputTerminal in; private OutputTerminal out; public void setBar(String bar) { this.bar = bar; } public String getBar() { return bar; } public void init() throws MediationConfigurationException { in = getMediationServices().getInputTerminal("in"); if(in == null) { throw new MediationConfigurationException("No input terminal named in"); } out = getMediationServices().getOutputTerminal("out"); if(out == null) { throw new MediationConfigurationException("No output terminal named out"); } // If we require bar to have a value, we can validate this in the // init method: if(bar == null) { throw new MediationConfigurationException("bar property not set"); } } public void mediate(InputTerminal inputTerminal, DataObject message} throws MediationConfigurationException, MediationBusinessException { // Do something with the message } }
The main work of the mediation primitive happens in the mediation
method. We can implement the body of the method to work on the message and
fire an output terminal accordingly:
public class FooMediation extends AbstractMediation { private String bar; private InputTerminal in; private OutputTerminal out; public void setBar(String bar) { this.bar = bar; } public String getBar() { return bar; } public void init() throws MediationConfigurationException { in = getMediationServices().getInputTerminal("in"); if(in == null) { throw new MediationConfigurationException("No input terminal named in"); } out = getMediationServices().getOutputTerminal("out"); if(out == null) { throw new MediationConfigurationException("No output terminal named out"); } // If we require bar to have a value, we can validate this in the // init method: if(bar == null) { throw new MediationConfigurationException("bar property not set"); } } public void mediate(InputTerminal inputTerminal, DataObject message} throws MediationConfigurationException, MediationBusinessException { try{ // Do something with the message message.setString("bar", bar); // fire the output terminal out.fire(message); } catch (Exception e){ throw new MediationBusinessException(e); } } }