You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@synapse.apache.org by su...@apache.org on 2010/12/13 12:12:59 UTC
svn commit: r1045064 -
/synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml
Author: supun
Date: Mon Dec 13 11:12:58 2010
New Revision: 1045064
URL: http://svn.apache.org/viewvc?rev=1045064&view=rev
Log:
applying SYNAPSE-711 many thanks udayanga for the contribution
Modified:
synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml
Modified: synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml
URL: http://svn.apache.org/viewvc/synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml?rev=1045064&r1=1045063&r2=1045064&view=diff
==============================================================================
--- synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml (original)
+++ synapse/trunk/java/src/site/xdoc/Synapse_Extending.xml Mon Dec 13 11:12:58 2010
@@ -6,519 +6,837 @@
</properties>
<head>
<style type="text/css" xml:space="preserve">
- .command {
- border: 1px dashed #3c78b5;
- text-align: left;
- background-color: #f0f0f0;
- padding: 3px;
- font-size: 11px;
- font-family: Courier;
- margin: 10px;
- line-height: 13px;
- }
- .consoleOutput {
- border: 1px dashed #3c78b5;
- font-size: 11px;
- font-family: Courier;
- margin: 10px;
- line-height: 13px;
- background-color: #f0f0f0;
- border-bottom: 1px dashed #3c78b5;
- padding: 3px;
- border-style: solid;
- }
- .info {
- border-style: solid;
- border-width: 1px;
- border-color: #090;
- background-color: #dfd;
- text-align:left;
- margin-top: 5px;
- margin-bottom: 5px;
- }
- li {
- font-family: Verdana, arial, sans-serif;
- font-size: 11px;
- line-height: 16px;
- color: #000000;
- font-weight: normal;
- }
- p {
- font-family: Verdana, arial, sans-serif;
- font-size: 11px;
- line-height: 16px;
- color: #000000;
- font-weight: normal;
- }
- pre {
- padding: 0px;
- margin-top: 5px;
- margin-left: 15px;
- margin-bottom: 5px;
- margin-right: 5px;
- text-align: left;
- background-color: #f0f0f0;
- padding: 3px;
- border: 1px dashed #3c78b5;
- font-size: 11px;
- font-family: Courier;
- margin: 10px;
- line-height: 13px;
- }
- h1 {
- font-size: 24px;
- line-height: normal;
- font-weight: bold;
- background-color: #f0f0f0;
- color: #003366;
- border-bottom: 1px solid #3c78b5;
- padding: 2px;
- margin: 36px 0px 4px 0px;
- }
- h2 {
- font-size: 18px;
- line-height: normal;
- font-weight: bold;
- background-color: #f0f0f0;
- border-bottom: 1px solid #3c78b5;
- padding: 2px;
- margin: 27px 0px 4px 0px;
- }
- h3 {
- font-size: 14px;
- line-height: normal;
- font-weight: bold;
- background-color: #f0f0f0;
- padding: 2px;
- margin: 21px 0px 4px 0px;
- }
- h4 {
- font-size: 12px;
- line-height: normal;
- font-weight: bold;
- background-color: #f0f0f0;
- padding: 2px;
- margin: 18px 0px 4px 0px;
- }</style>
+ .command {
+ border: 1px dashed #3c78b5;
+ text-align: left;
+ background-color: #f0f0f0;
+ padding: 3px;
+ font-size: 11px;
+ font-family: Courier;
+ margin: 10px;
+ line-height: 13px;
+ }
+ .consoleOutput {
+ border: 1px dashed #3c78b5;
+ font-size: 11px;
+ font-family: Courier;
+ margin: 10px;
+ line-height: 13px;
+ background-color: #f0f0f0;
+ border-bottom: 1px dashed #3c78b5;
+ padding: 3px;
+ border-style: solid;
+ }
+ .info {
+ border-style: solid;
+ border-width: 1px;
+ border-color: #090;
+ background-color: #dfd;
+ text-align:left;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ }
+ li {
+ font-family: Verdana, arial, sans-serif;
+ font-size: 11px;
+ line-height: 16px;
+ color: #000000;
+ font-weight: normal;
+ }
+ p {
+ font-family: Verdana, arial, sans-serif;
+ font-size: 11px;
+ line-height: 16px;
+ color: #000000;
+ font-weight: normal;
+ }
+ pre {
+ padding: 0px;
+ margin-top: 5px;
+ margin-left: 15px;
+ margin-bottom: 5px;
+ margin-right: 5px;
+ text-align: left;
+ background-color: #f0f0f0;
+ padding: 3px;
+ border: 1px dashed #3c78b5;
+ font-size: 11px;
+ font-family: Courier;
+ margin: 10px;
+ line-height: 13px;
+ }
+ h1 {
+ font-size: 24px;
+ line-height: normal;
+ font-weight: bold;
+ background-color: #f0f0f0;
+ color: #003366;
+ border-bottom: 1px solid #3c78b5;
+ padding: 2px;
+ margin: 36px 0px 4px 0px;
+ }
+ h2 {
+ font-size: 18px;
+ line-height: normal;
+ font-weight: bold;
+ background-color: #f0f0f0;
+ border-bottom: 1px solid #3c78b5;
+ padding: 2px;
+ margin: 27px 0px 4px 0px;
+ }
+ h3 {
+ font-size: 14px;
+ line-height: normal;
+ font-weight: bold;
+ background-color: #f0f0f0;
+ padding: 2px;
+ margin: 21px 0px 4px 0px;
+ }
+ h4 {
+ font-size: 12px;
+ line-height: normal;
+ font-weight: bold;
+ background-color: #f0f0f0;
+ padding: 2px;
+ margin: 18px 0px 4px 0px;
+ }
+ </style>
</head>
- <body>
- <div style="margin-top:-40px; float:right; _margin-top:0px;">
- <img alt="Synapse logo"
- src="images/synapse-logo-web2.png" width="197"
- height="82"/>
- </div>
- <div>
- <h1>
- Apache Synapse ESB - Extending...
- </h1>
- </div>
- <h2>
- Writing custom Mediator implementations
- </h2>
- <p>
- The primary interface of the Synapse API is the MessageContext interface
- defined below. This essentially defines the per-message context passed
- through the chain of mediators, for each and every message received and
- processed by Synapse. Each message instance is wrapped within a
- MessageContext instance, and the message context is set with the
- references to the SynapseConfiguration and SynapseEnvironment objects. The
- <a href="apidocs/org/apache/synapse/config/SynapseConfiguration.html">SynapseConfiguration</a>
- object holds the global configuration model that defines
- mediation rules, local registry entries and other and configuration, while
- the <a href="apidocs/org/apache/synapse/core/SynapseEnvironment.html">SynapseEnvironment</a>
- object gives access to the underlying SOAP implementation used -
- Axis2. A typical mediator would need to manipulate the MessageContext by
- referring to the SynapseConfiguration. However it is strongly recommended
- that the SynapseConfiguration is not updated by mediator instances as it
- is shared by all messages, and may be updated by Synapse administration or
- configuration modules. Mediator instances may store local message
- properties into the MessageContext for later retrieval by successive
- mediators.<br/>
- </p>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/MessageContext.java?view=markup">MessageContext
- Interface</a>
- </h4>
- <p/>
-<pre xml:space="preserve">package org.apache.synapse;
-
-import ...
-
-public interface MessageContext {
-
- /**
- * Get a reference to the current SynapseConfiguration
- *
- * @return the current synapse configuration
- */
- public SynapseConfiguration getConfiguration();
-
- /**
- * Set or replace the Synapse Configuration instance to be used. May be used to
- * programatically change the configuration at runtime etc.
- *
- * @param cfg The new synapse configuration instance
- */
- public void setConfiguration(SynapseConfiguration cfg);
-
- /**
- * Returns a reference to the host Synapse Environment
- * @return the Synapse Environment
- */
- public SynapseEnvironment getEnvironment();
-
- /**
- * Sets the SynapseEnvironment reference to this context
- * @param se the reference to the Synapse Environment
- */
- public void setEnvironment(SynapseEnvironment se);
-
- /**
- * Get the value of a custom (local) property set on the message instance
- * @param key key to look up property
- * @return value for the given key
- */
- public Object getProperty(String key);
-
- /**
- * Set a custom (local) property with the given name on the message instance
- * @param key key to be used
- * @param value value to be saved
- */
- public void setProperty(String key, Object value);
-
- /**
- * Returns the Set of keys over the properties on this message context
- * @return a Set of keys over message properties
- */
- public Set getPropertyKeySet();
-
- /**
- * Get the SOAP envelope of this message
- * @return the SOAP envelope of the message
- */
- public SOAPEnvelope getEnvelope();
-
- /**
- * Sets the given envelope as the current SOAPEnvelope for this message
- * @param envelope the envelope to be set
- * @throws org.apache.axis2.AxisFault on exception
- */
- public void setEnvelope(SOAPEnvelope envelope) throws AxisFault;
-
- /**
- * SOAP message related getters and setters
- */
- public ....get/set()...
-
-}</pre>
- <p>
- The MessageContext interface is based on the Axis2 MessageContext
- interface, and uses the Axis2 EndpointReference and
- SOAPEnvelope classes/interfaces. The purpose of this interface is to
- capture a message as it flows through the system. As you will see the
- message payload is represented using the SOAP infoset. Binary messages can
- be embedded in the Envelope using MTOM or SwA attachments using the AXIOM
- object model.
- </p>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/Mediator.java?view=markup">Mediator
- interface</a>
- </h4>
- <p>
- The second key interface for mediator writers is the Mediator interface:
- </p>
-<pre xml:space="preserve">package org.apache.synapse;
-
-import org.apache.synapse.MessageContext;
-
-/**
- * All Synapse mediators must implement this Mediator interface. As a message passes
- * through the synapse system, each mediator's mediate() method is invoked in the
- * sequence/order defined in the SynapseConfiguration.
- */
-public interface <span style="font-weight: bold;">Mediator </span>{
-
- /**
- * Invokes the mediator passing the current message for mediation. Each
- * mediator performs its mediation action, and returns true if mediation
- * should continue, or false if further mediation should be aborted.
- *
- * @param synCtx the current message for mediation
- * @return true if further mediation should continue
- */
- public boolean mediate(MessageContext synCtx);
-
- /**
- * This is used for debugging purposes and exposes the type of the current
- * mediator for logging and debugging purposes
- * @return a String representation of the mediator type
- */
- public String getType();
-}</pre>
- <p>
- A mediator can read and/or modify the message encapsulated in the MessageContext in
- any suitable manner - adjusting the routing headers or changing the
- message body. If the mediate() method returns false, it signals to the
- Synapse processing model to stop further processing of the message. For
- example, if the mediator is a security agent it may decide that this
- message is dangerous and should not be processed further. This is
- generally the exception as mediators are usually designed to co-operate to
- process the message onwards.
- </p>
- <h3>
- Leaf and Node Mediators, List mediators and Filter mediators
- </h3>
- <p>
- Mediators may be Node mediators (i.e. these that can contain child
- mediators) or Leaf mediators (mediators that does not hold any other child
- mediators). A Node mediator must implement the
- org.apache.synapse.mediators.ListMediator interface listed below, or extend from
- the org.apache.synapse.mediators.AbstractListMediator.
- </p>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/ListMediator.java?view=markup">The
- ListMediator interface</a>
- </h4>
-<pre xml:space="preserve">package org.apache.synapse.mediators;
-
-import java.util.List;
-
-/**
-* The List mediator executes a given sequence/list of child mediators
-*/
-public interface ListMediator extends Mediator {
- /**
- * Appends the specified mediator to the end of this mediator's (children) list
- * @param m the mediator to be added
- * @return true (as per the general contract of the Collection.add method)
- */
- public boolean addChild(Mediator m);
-
- /**
- * Appends all of the mediators in the specified collection to the end of this mediator's (children)
- * list, in the order that they are returned by the specified collection's iterator
- * @param c the list of mediators to be added
- * @return true if this list changed as a result of the call
- */
- public boolean addAll(List c);
-
- /**
- * Returns the mediator at the specified position
- * @param pos index of mediator to return
- * @return the mediator at the specified position in this list
- */
- public Mediator getChild(int pos);
-
- /**
- * Removes the first occurrence in this list of the specified mediator
- * @param m mediator to be removed from this list, if present
- * @return true if this list contained the specified mediator
- */
- public boolean removeChild(Mediator m);
-
- /**
- * Removes the mediator at the specified position in this list
- * @param pos the index of the mediator to remove
- * @return the mediator previously at the specified position
- */
- public Mediator removeChild(int pos);
-
- /**
- * Return the list of mediators of this List mediator instance
- * @return the child/sub mediator list
- */
- public List getList();
-}</pre>
- <p>
- A ListMediator implementation should call super.mediate(synCtx) to process
- its sub mediator sequence. A FilterMediator is a ListMediator which
- executes its sequence of sub mediators on successful outcome of a test
- condition. The Mediator instance which performs filtering should implement
- the FilterMediator interface.
- </p>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/FilterMediator.java?view=markup">FilterMediator
- interface</a>
- </h4>
-<pre xml:space="preserve">package org.apache.synapse.mediators;
-
-import org.apache.synapse.MessageContext;
-
-/**
- * The filter mediator is a list mediator, which executes the given (sub) list of mediators
- * if the specified condition is satisfied
- *
- * @see FilterMediator#test(org.apache.synapse.MessageContext)
- */
-public interface <span style="font-weight: bold;">FilterMediator </span>extends ListMediator {
-
- /**
- * Should return true if the sub/child mediators should execute. i.e. if the filter
- * condition is satisfied
- * @param synCtx
- * @return true if the configured filter condition evaluates to true
- */
- public boolean test(MessageContext synCtx);
-}</pre>
- <h2>
- Writing custom Configuration implementations for mediators
- </h2>
- <p>
- You may write your own custom configurator for the Mediator implementation
- you write without relying on the Class mediator or Spring extension for
- its initialization. You could thus write a MediatorFactory implementation
- which defines how to digest a custom XML configuration element to be used
- to create and configure the custom mediator instance. A MediatorSerializer
- implementation defines how a configuration should be serialized back into
- an XML configuration. The custom MediatorFactory & MediatorSerializer
- implementations and the mediator class/es must be bundled in a JAR file
- conforming to the J2SE Service Provider model (See the description for
- Extensions below for more details and examples) and placed into the
- SYNAPSE_HOME/lib folder, so that the Synapse runtime could find and load
- the definition. Essentially this means that a custom JAR file must bundle
- your class implementing the Mediator interface, and the MediatorFactory
- implementation class and contain two text files named
- "org.apache.synapse.config.xml.MediatorFactory" and
- "org.apache.synapse.config.xml.MediatorSerializer" which will contain the
- fully qualified name(s) of your MediatorFactory and MediatorSerializer
- implementation classes. You should also place any dependency JARs into the
- same lib folder so that the correct classpath references could be made.
- The MediatorFactory interface listing is given below, which you should
- implement, and its getTagQName() method must define the fully qualified
- element of interest for custom configuration. The Synapse initialization
- will call back to this MediatorFactory instance through the
- createMediator(OMElement elem) method passing in this XML element, so that
- an instance of the mediator could be created utilizing the custom XML
- specification and returned. See the ValidateMediator and the
- ValidateMediatorFactory classes under modules/extensions in the Synapse
- source distribution for examples.
- </p>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactory.java?view=markup">The
- MediatorFactory interface</a>
- </h4>
-<pre xml:space="preserve">package org.apache.synapse.config.xml;
-
-import ...
-
-/**
- * A mediator factory capable of creating an instance of a mediator through a given
- * XML should implement this interface
- */
-public interface MediatorFactory {
- /**
- * Creates an instance of the mediator using the OMElement
- * @param elem
- * @return the created mediator
- */
- public Mediator createMediator(OMElement elem);
-
- /**
- * The QName of this mediator element in the XML config
- * @return QName of the mediator element
- */
- public QName getTagQName();
-}</pre>
- <p/>
- <h4>
- <a
- href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorSerializer.java?view=markup">The
- MediatorSerializer interface</a>
- </h4>
-<pre xml:space="preserve">package org.apache.synapse.config.xml;
-
-import ...
-
-/**
- * Interface which should be implemented by mediator serializers. Does the
- * reverse of the MediatorFactory
- */
-public interface MediatorSerializer {
-
- /**
- * Return the XML representation of this mediator
- * @param m mediator to be serialized
- * @param parent the OMElement to which the serialization should be attached
- * @return the serialized mediator XML
- */
- public OMElement serializeMediator(OMElement parent, Mediator m);
-
- /**
- * Return the class name of the mediator which can be serialized
- * @return the class name
- */
- public String getMediatorClassName();
-}</pre>
- <h2>
- Configuring mediators
- </h2>
- <p>
- Mediators could access the Synapse registry to load resources and
- configure the local behaviour. Refer to the Spring mediator and Script
- mediator implementations for examples on how this could be achieved.
- </p>
- <h4>
- Loading of Extensions by the Synapse runtime
- </h4>
- <p>
- Synapse loads available extensions from the runtime classpath using the <a
- href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">J2SE
- Service Provider model</a>. This essentially iterates over the
- available JAR files, for a META-INF/services directory within each file,
- and looks for a text file with the name
- org.apache.synapse.config.xml.MediatorFactory which contains a list of
- fully qualified classname that implement the above interface, listing each
- class in a separate line. e.g. The built-in synapse-extensions.jar
- contains the following structure
- </p>
-<pre xml:space="preserve">synapse-extensions.jar
- /META-INF/services
- org.apache.synapse.config.xml.MediatorFactory
- org.apache.synapse.config.xml.MediatorSerializer
- /... the implementation classes as usual...</pre>
- <h2 id="synObservers">
- Writing Synapse Observers
- </h2>
- <p>
- A Synapse observer is developed by either implementing the
- org.apache.synapse.config.SynapseObserver interface or by extending the
- org.apache.synapse.config.AbstractSynapseObserver class. A Synapse observer is notified
- by the Synapse configuration when new elements are added to the configuration and
- when existing elements are removed from the configuration. The following event
- handlers are available to the Synapse observer implementations.
- </p>
-<pre xml:space="preserve">
- public void sequenceAdded(Mediator sequence);
- public void sequenceRemoved(Mediator sequence);
- public void entryAdded(Entry entry);
- public void entryRemoved(Entry entry);
- public void endpointAdded(Endpoint endpoint);
- public void endpointRemoved(Endpoint endpoint);
- public void proxyServiceAdded(ProxyService proxy);
- public void proxyServiceRemoved(ProxyService proxy);
- public void startupAdded(Startup startup);
- public void startupRemoved(Startup startup);
- public void eventSourceAdded(SynapseEventSource eventSource);
- public void eventSourceRemoved(SynapseEventSource eventSource);
-</pre>
- <p>
- The AbstractSynapseObserver provides default implementations to all these
- event handlers. It simply logs any received events.
- </p>
- <p>
- In situations where the custom code has access to the SynapseConfiguration class
- observers can be directly registered with the SynapseConfiguration by using the
- registerObserver(SynapseObserver o) method. Otherwise SynapseObserver implementations
- can be defined in the synapse.properties file which resides in the SYNAPSE_HOME/lib
- directory. The following example shows how two observers are registered with the
- Synapse configuration using the synapse.properties file.
- </p>
- <pre xml:space="preserve">synapse.observers=test.LoggingObserverImpl, test.SimpleObserverImpl</pre>
- </body>
+ <body>
+ <div style="margin-top:-40px; float:right; _margin-top:0px;">
+ <img alt="Synapse logo"
+ src="images/synapse-logo-web2.png" width="197"
+ height="82"/>
+ </div>
+ <div>
+ <h1>
+ Apache Synapse ESB - Extending...
+ </h1>
+ </div>
+ <h2>
+ Writing custom Mediator implementations
+ </h2>
+ <p>
+ The primary interface of the Synapse API is the MessageContext interface
+ defined below. This essentially defines the per-message context passed
+ through the chain of mediators, for each and every message received and
+ processed by Synapse. Each message instance is wrapped within a
+ MessageContext instance, and the message context is set with the
+ references to the SynapseConfiguration and SynapseEnvironment objects. The
+ <a href="apidocs/org/apache/synapse/config/SynapseConfiguration.html">
+ SynapseConfiguration
+ </a>
+ object holds the global configuration model that defines
+ mediation rules, local registry entries and other and configuration, while
+ the
+ <a href="apidocs/org/apache/synapse/core/SynapseEnvironment.html">SynapseEnvironment</a>
+ object gives access to the underlying SOAP implementation used -
+ Axis2. A typical mediator would need to manipulate the MessageContext by
+ referring to the SynapseConfiguration. However it is strongly recommended
+ that the SynapseConfiguration is not updated by mediator instances as it
+ is shared by all messages, and may be updated by Synapse administration or
+ configuration modules. Mediator instances may store local message
+ properties into the MessageContext for later retrieval by successive
+ mediators.
+ <br/>
+ </p>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/MessageContext.java?view=markup">
+ MessageContext
+ Interface
+ </a>
+ </h4>
+ <p/>
+ <pre xml:space="preserve">package org.apache.synapse;
+
+ import ...
+
+ public interface MessageContext {
+
+ /**
+ * Get a reference to the current SynapseConfiguration
+ *
+ * @return the current synapse configuration
+ */
+ public SynapseConfiguration getConfiguration();
+
+ /**
+ * Set or replace the Synapse Configuration instance to be used. May be used to
+ * programatically change the configuration at runtime etc.
+ *
+ * @param cfg The new synapse configuration instance
+ */
+ public void setConfiguration(SynapseConfiguration cfg);
+
+ /**
+ * Returns a reference to the host Synapse Environment
+ * @return the Synapse Environment
+ */
+ public SynapseEnvironment getEnvironment();
+
+ /**
+ * Sets the SynapseEnvironment reference to this context
+ * @param se the reference to the Synapse Environment
+ */
+ public void setEnvironment(SynapseEnvironment se);
+
+ /**
+ * Get the value of a custom (local) property set on the message instance
+ * @param key key to look up property
+ * @return value for the given key
+ */
+ public Object getProperty(String key);
+
+ /**
+ * Set a custom (local) property with the given name on the message instance
+ * @param key key to be used
+ * @param value value to be saved
+ */
+ public void setProperty(String key, Object value);
+
+ /**
+ * Returns the Set of keys over the properties on this message context
+ * @return a Set of keys over message properties
+ */
+ public Set getPropertyKeySet();
+
+ /**
+ * Get the SOAP envelope of this message
+ * @return the SOAP envelope of the message
+ */
+ public SOAPEnvelope getEnvelope();
+
+ /**
+ * Sets the given envelope as the current SOAPEnvelope for this message
+ * @param envelope the envelope to be set
+ * @throws org.apache.axis2.AxisFault on exception
+ */
+ public void setEnvelope(SOAPEnvelope envelope) throws AxisFault;
+
+ /**
+ * SOAP message related getters and setters
+ */
+ public ....get/set()...
+
+ }
+ </pre>
+ <p>
+ The MessageContext interface is based on the Axis2 MessageContext
+ interface, and uses the Axis2 EndpointReference and
+ SOAPEnvelope classes/interfaces. The purpose of this interface is to
+ capture a message as it flows through the system. As you will see the
+ message payload is represented using the SOAP infoset. Binary messages can
+ be embedded in the Envelope using MTOM or SwA attachments using the AXIOM
+ object model.
+ </p>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/Mediator.java?view=markup">
+ Mediator
+ interface
+ </a>
+ </h4>
+ <p>
+ The second key interface for mediator writers is the Mediator interface:
+ </p>
+ <pre xml:space="preserve">package org.apache.synapse;
+
+ import org.apache.synapse.MessageContext;
+
+ /**
+ * All Synapse mediators must implement this Mediator interface. As a message passes
+ * through the synapse system, each mediator's mediate() method is invoked in the
+ * sequence/order defined in the SynapseConfiguration.
+ */
+ public interface<span style="font-weight: bold;">Mediator</span>{
+
+ /**
+ * Invokes the mediator passing the current message for mediation. Each
+ * mediator performs its mediation action, and returns true if mediation
+ * should continue, or false if further mediation should be aborted.
+ *
+ * @param synCtx the current message for mediation
+ * @return true if further mediation should continue
+ */
+ public boolean mediate(MessageContext synCtx);
+
+ /**
+ * This is used for debugging purposes and exposes the type of the current
+ * mediator for logging and debugging purposes
+ * @return a String representation of the mediator type
+ */
+ public String getType();
+ }
+ </pre>
+ <p>
+ A mediator can read and/or modify the message encapsulated in the MessageContext in
+ any suitable manner - adjusting the routing headers or changing the
+ message body. If the mediate() method returns false, it signals to the
+ Synapse processing model to stop further processing of the message. For
+ example, if the mediator is a security agent it may decide that this
+ message is dangerous and should not be processed further. This is
+ generally the exception as mediators are usually designed to co-operate to
+ process the message onwards.
+ </p>
+ <h3>
+ Leaf and Node Mediators, List mediators and Filter mediators
+ </h3>
+ <p>
+ Mediators may be Node mediators (i.e. these that can contain child
+ mediators) or Leaf mediators (mediators that does not hold any other child
+ mediators). A Node mediator must implement the
+ org.apache.synapse.mediators.ListMediator interface listed below, or extend from
+ the org.apache.synapse.mediators.AbstractListMediator.
+ </p>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/ListMediator.java?view=markup">
+ The
+ ListMediator interface
+ </a>
+ </h4>
+ <pre xml:space="preserve">package org.apache.synapse.mediators;
+
+ import java.util.List;
+
+ /**
+ * The List mediator executes a given sequence/list of child mediators
+ */
+ public interface ListMediator extends Mediator {
+ /**
+ * Appends the specified mediator to the end of this mediator's (children) list
+ * @param m the mediator to be added
+ * @return true (as per the general contract of the Collection.add method)
+ */
+ public boolean addChild(Mediator m);
+
+ /**
+ * Appends all of the mediators in the specified collection to the end of this mediator's
+ (children)
+ * list, in the order that they are returned by the specified collection's iterator
+ * @param c the list of mediators to be added
+ * @return true if this list changed as a result of the call
+ */
+ public boolean addAll(List c);
+
+ /**
+ * Returns the mediator at the specified position
+ * @param pos index of mediator to return
+ * @return the mediator at the specified position in this list
+ */
+ public Mediator getChild(int pos);
+
+ /**
+ * Removes the first occurrence in this list of the specified mediator
+ * @param m mediator to be removed from this list, if present
+ * @return true if this list contained the specified mediator
+ */
+ public boolean removeChild(Mediator m);
+
+ /**
+ * Removes the mediator at the specified position in this list
+ * @param pos the index of the mediator to remove
+ * @return the mediator previously at the specified position
+ */
+ public Mediator removeChild(int pos);
+
+ /**
+ * Return the list of mediators of this List mediator instance
+ * @return the child/sub mediator list
+ */
+ public List getList();
+ }
+ </pre>
+ <p>
+ A ListMediator implementation should call super.mediate(synCtx) to process
+ its sub mediator sequence. A FilterMediator is a ListMediator which
+ executes its sequence of sub mediators on successful outcome of a test
+ condition. The Mediator instance which performs filtering should implement
+ the FilterMediator interface.
+ </p>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/FilterMediator.java?view=markup">
+ FilterMediator
+ interface
+ </a>
+ </h4>
+ <pre xml:space="preserve">package org.apache.synapse.mediators;
+
+ import org.apache.synapse.MessageContext;
+
+ /**
+ * The filter mediator is a list mediator, which executes the given (sub) list of
+ mediators
+ * if the specified condition is satisfied
+ *
+ * @see FilterMediator#test(org.apache.synapse.MessageContext)
+ */
+ public interface<span style="font-weight: bold;">FilterMediator</span>extends
+ ListMediator {
+
+ /**
+ * Should return true if the sub/child mediators should execute. i.e. if the filter
+ * condition is satisfied
+ * @param synCtx
+ * @return true if the configured filter condition evaluates to true
+ */
+ public boolean test(MessageContext synCtx);
+ }
+ </pre>
+ <h2>
+ Writing custom Configuration implementations for mediators
+ </h2>
+ <p>
+ You may write your own custom configurator for the Mediator implementation
+ you write without relying on the Class mediator or Spring extension for
+ its initialization. You could thus write a MediatorFactory implementation
+ which defines how to digest a custom XML configuration element to be used
+ to create and configure the custom mediator instance. A MediatorSerializer
+ implementation defines how a configuration should be serialized back into
+ an XML configuration. The custom MediatorFactory & MediatorSerializer
+ implementations and the mediator class/es must be bundled in a JAR file
+ conforming to the J2SE Service Provider model (See the description for
+ Extensions below for more details and examples) and placed into the
+ SYNAPSE_HOME/lib folder, so that the Synapse runtime could find and load
+ the definition. Essentially this means that a custom JAR file must bundle
+ your class implementing the Mediator interface, and the MediatorFactory
+ implementation class and contain two text files named
+ "org.apache.synapse.config.xml.MediatorFactory" and
+ "org.apache.synapse.config.xml.MediatorSerializer" which will contain the
+ fully qualified name(s) of your MediatorFactory and MediatorSerializer
+ implementation classes. You should also place any dependency JARs into the
+ same lib folder so that the correct classpath references could be made.
+ The MediatorFactory interface listing is given below, which you should
+ implement, and its getTagQName() method must define the fully qualified
+ element of interest for custom configuration. The Synapse initialization
+ will call back to this MediatorFactory instance through the
+ createMediator(OMElement elem) method passing in this XML element, so that
+ an instance of the mediator could be created utilizing the custom XML
+ specification and returned. See the ValidateMediator and the
+ ValidateMediatorFactory classes under modules/extensions in the Synapse
+ source distribution for examples.
+ </p>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactory.java?view=markup">
+ The
+ MediatorFactory interface
+ </a>
+ </h4>
+ <pre xml:space="preserve">package org.apache.synapse.config.xml;
+
+ import ...
+
+ /**
+ * A mediator factory capable of creating an instance of a mediator through a given
+ * XML should implement this interface
+ */
+ public interface MediatorFactory {
+ /**
+ * Creates an instance of the mediator using the OMElement
+ * @param elem
+ * @return the created mediator
+ */
+ public Mediator createMediator(OMElement elem);
+
+ /**
+ * The QName of this mediator element in the XML config
+ * @return QName of the mediator element
+ */
+ public QName getTagQName();
+ }
+ </pre>
+ <p/>
+ <h4>
+ <a
+ href="http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorSerializer.java?view=markup">
+ The
+ MediatorSerializer interface
+ </a>
+ </h4>
+ <pre xml:space="preserve">package org.apache.synapse.config.xml;
+
+ import ...
+
+ /**
+ * Interface which should be implemented by mediator serializers. Does the
+ * reverse of the MediatorFactory
+ */
+ public interface MediatorSerializer {
+
+ /**
+ * Return the XML representation of this mediator
+ * @param m mediator to be serialized
+ * @param parent the OMElement to which the serialization should be attached
+ * @return the serialized mediator XML
+ */
+ public OMElement serializeMediator(OMElement parent, Mediator m);
+
+ /**
+ * Return the class name of the mediator which can be serialized
+ * @return the class name
+ */
+ public String getMediatorClassName();
+ }
+ </pre>
+ <h2>
+ Configuring mediators
+ </h2>
+ <p>
+ Mediators could access the Synapse registry to load resources and
+ configure the local behaviour. Refer to the Spring mediator and Script
+ mediator implementations for examples on how this could be achieved.
+ </p>
+ <h4>
+ Loading of Extensions by the Synapse runtime
+ </h4>
+ <p>
+ Synapse loads available extensions from the runtime classpath using the<a
+ href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">J2SE
+ Service Provider model</a>. This essentially iterates over the
+ available JAR files, for a META-INF/services directory within each file,
+ and looks for a text file with the name
+ org.apache.synapse.config.xml.MediatorFactory which contains a list of
+ fully qualified classname that implement the above interface, listing each
+ class in a separate line. e.g. The built-in synapse-extensions.jar
+ contains the following structure
+ </p>
+ <pre xml:space="preserve">synapse-extensions.jar
+ /META-INF/services
+ org.apache.synapse.config.xml.MediatorFactory
+ org.apache.synapse.config.xml.MediatorSerializer
+ /... the implementation classes as usual...
+ </pre>
+ <h2 id="synObservers">
+ Writing Synapse Observers
+ </h2>
+ <p>
+ A Synapse observer is developed by either implementing the
+ org.apache.synapse.config.SynapseObserver interface or by extending the
+ org.apache.synapse.config.AbstractSynapseObserver class. A Synapse observer is notified
+ by the Synapse configuration when new elements are added to the configuration and
+ when existing elements are removed from the configuration. The following event
+ handlers are available to the Synapse observer implementations.
+ </p>
+ <pre xml:space="preserve">
+ public void sequenceAdded(Mediator sequence);
+ public void sequenceRemoved(Mediator sequence);
+ public void entryAdded(Entry entry);
+ public void entryRemoved(Entry entry);
+ public void endpointAdded(Endpoint endpoint);
+ public void endpointRemoved(Endpoint endpoint);
+ public void proxyServiceAdded(ProxyService proxy);
+ public void proxyServiceRemoved(ProxyService proxy);
+ public void startupAdded(Startup startup);
+ public void startupRemoved(Startup startup);
+ public void eventSourceAdded(SynapseEventSource eventSource);
+ public void eventSourceRemoved(SynapseEventSource eventSource);
+ </pre>
+ <p>
+ The AbstractSynapseObserver provides default implementations to all these
+ event handlers. It simply logs any received events.
+ </p>
+ <p>
+ In situations where the custom code has access to the SynapseConfiguration class
+ observers can be directly registered with the SynapseConfiguration by using the
+ registerObserver(SynapseObserver o) method. Otherwise SynapseObserver implementations
+ can be defined in the synapse.properties file which resides in the SYNAPSE_HOME/lib
+ directory. The following example shows how two observers are registered with the
+ Synapse configuration using the synapse.properties file.
+ </p>
+ <pre xml:space="preserve">synapse.observers=test.LoggingObserverImpl,
+ test.SimpleObserverImpl
+ </pre>
+
+ <h2 id="synXpathExtensions">
+ Synapse Xpath Extension Framework
+ </h2>
+ <p>
+ Synapse configuration language is a powerful and flexible tool to perform
+ authentication, validation, transformation, logging, routing based on the content etc.
+ It could be easily extended, with configuration extensions , mediation extensions and
+ even expression level extension. An expression is a lowest level particle in the
+ synapase configuration. To be precise , unlike static values ,expressions can be used to
+ define dynamically extracted values (using xpath) in a synapse configuration.
+ Mediators extensively uses expressions to extract properties from message context.
+ Expression is defined under attribute "expression" of a particular configuration. (see
+ property/header/iterator mediator ) .Although expressions can be purely xpath , synapse
+ allows extended to define extended expressions as well. These special xpath expressions
+ can be two fold , that is ,
+ </p>
+ <pre xml:space="preserve">
+ 1.xpath variable expressions
+ 2.xpath function expressions
+ </pre>
+ <p>
+ Synapse allows us to access xpath variables with "$" . Currently there are several
+ predefined synapse xpath variables avaiable.
+ </p>
+ <pre xml:space="preserve">
+ Ie:- $body - message SOAP body
+ $header ? message SOAP header
+ $ctxt:SOME_PROPERTY ? a property belonging to synapse meessage context scope
+ $axis2:SOME_PROPERTY ? a property belonging to axis2 meessage context scope
+ $trp:SOME_TRANSPORT_HEADER ? a transport header
+ </pre>
+ <p>
+ Synapse get-property() is an example xpath function expressions. The get-property()
+ function allows any XPath expression used in a configuration to lookup information from
+ the current message context. Similar to above , It is possible to retrieve properties
+ previously set with the property mediator, and/or information from the Synapse or Axis2
+ message contexts or transport header using get-property().
+ </p>
+ <p>
+ see synapse documentation for more details on usage of these expressions.
+ Synapse Xpath extension framework allows users to further extend xpath expressions to
+ suite user requirement. More specifically it allows users to define custom xpath
+ expressions and custom xpath functions that is required in a specific usecase
+ configuration scenario. Let's see how we can do this. We start by writng our HELLO_WORLD
+ custom xpath variable and hello-world() custom xpath function.
+ </p>
+ <h4>
+ Implementing HELLO_WORLD custom xpath variable
+ </h4>
+ <p>
+ Before going into implementation details , let me first define our final objective here.
+ What we need to do is to expose an HELLO_WORLD message in xml format to outside , so
+ that users would be able to access it using a xpath expression="$HELLOWORLD/...".
+ Following is the HELLO_WORLD mesasge we have.
+ </p>
+ <pre xml:space="preserve">
+ <HELLO_WORLD>
+ <name>Synapse</name>
+ <version>2.0.0</version>
+ <release_date>20/12/2010</release_date>
+ </HELLO_WORLD>
+ </pre>
+ <p>Every custom synapse xpath extension should implement
+ org.apache.synapse.util.xpath.ext.SynapseXpathVariableResolver interface to expose a
+ custom xpath variable. This interface consists of two methods , #getResolvingQName ,
+ #resolve . First interface method is used to indicate Synapse the fully qualified
+ variable name that this extesion support (in our case it is HELLO_WORLD). Later method
+ should contain what ever resolving logic required to give the desired output.(in our
+ case it should return HELLO_WORLD element) . Following is the implementation of our
+ custom xpath variable HELLO_WORLD,
+ </p>
+ <pre xml:space="preserve">
+ package org.sample;
+
+ import org.apache.axiom.om.OMAbstractFactory;
+ import org.apache.axiom.om.OMElement;
+ import org.apache.axiom.om.OMFactory;
+ import org.apache.synapse.MessageContext;
+ import org.apache.synapse.util.xpath.ext.SynapseXpathVariableResolver;
+
+ import javax.xml.namespace.QName;
+
+ public class HelloWorldXpathVariableResolver implements SynapseXpathVariableResolver {
+
+ public static final QName HELLO_WORLD = new QName("HELLO_WORLD");
+
+ public Object resolve(MessageContext messageContext) {
+ //create Hello world message
+ OMFactory factory = OMAbstractFactory.getOMFactory();
+ OMElement helloWorldElement = factory.createOMElement(HELLO_WORLD);
+
+ OMElement nameElement = factory.createOMElement(new QName("name"));
+ nameElement.setText("synapse");
+ OMElement versionElem = factory.createOMElement(new QName("version"));
+ versionElem.setText("3.1.0");
+ OMElement releaseDateElem = factory.createOMElement(new QName("release_date"));
+ releaseDateElem.setText("12/12/2010");
+
+ helloWorldElement.addChild(nameElement);
+ helloWorldElement.addChild(versionElem);
+ helloWorldElement.addChild(releaseDateElem);
+
+ return helloWorldElement;
+ }
+
+ public QName getResolvingQName() {
+ //to support xpath expression="$HELLO_WORLD"
+ return HELLO_WORLD;
+ }
+
+ }
+ </pre>
+ <p>
+ with implementation in place mediators can refer version , name , release date on
+ HELLO_WORLD message using expression="$HELLO_WORLD/version" , etc
+ </p>
+ <h4>
+ Implementing hello-world() custom xpath function
+ </h4>
+ <p>
+ Having an xpath function extension is easy as implementing an xpath variable extension.
+ In this case Extension class should implement
+ org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider . This interface
+ also do have methods , #getResolvingQName and #getInitializedExtFunction . First method
+ serves the same purpose as in the previous example. However later method should be
+ implementated in such a way that this extension should return a custom jaxen function to
+ synapse , initialized with synapse message context. It is extension developers
+ responsibility to provide a properly initialized xpath function so that it can be
+ resolved at runtime. Our sample implementation is shown below
+ </p>
+ <pre xml:space="preserve">
+ package org.sample;
+
+ import org.apache.synapse.MessageContext;
+ import org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider;
+ import org.jaxen.Function;
+ import javax.xml.namespace.QName;
+
+ public class HelloWorldXpathFunctionProvider implements SynapseXpathFunctionContextProvider {
+
+ public Function getInitializedExtFunction(MessageContext messageContext) {
+ CustomHelloWorldFunction helloWorldFunction = new CustomHelloWorldFunction(messageContext);
+ return helloWorldFunction;
+ }
+
+ public QName getResolvingQName() {
+ //letting know synapse new hello-world extension function
+ return new QName("hello-world");
+ }
+ }
+
+ </pre>
+ <p>
+ Shown bellow is the custom xpath function returned by our xpath function extension. Note
+ that this should implement org.jaxen.Function to resolve xpath .
+ </p>
+ <pre xml:space="preserve">
+ package org.sample;
+
+ import org.apache.axiom.om.OMAbstractFactory;
+ import org.apache.axiom.om.OMElement;
+ import org.apache.axiom.om.OMFactory;
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
+ import org.apache.synapse.MessageContext;
+ import org.apache.synapse.SynapseConstants;
+ import org.jaxen.Context;
+ import org.jaxen.Function;
+ import org.jaxen.FunctionCallException;
+ import org.jaxen.function.StringFunction;
+
+ import javax.xml.namespace.QName;
+ import java.util.List;
+
+
+ public class CustomHelloWorldFunction implements Function {
+ private MessageContext synCtx;
+
+ private Log log = LogFactory.getLog(CustomHelloWorldFunction.class);
+ private static final Log trace = LogFactory.getLog(SynapseConstants.TRACE_LOGGER);
+
+ private String NULL_STRING = "";
+ public static final QName HELLO_WORLD = new QName("HELLO_WORLD");
+ private OMElement helloWorld;
+
+ public CustomHelloWorldFunction(MessageContext ctxt) {
+ this.synCtx = ctxt;
+ //create hello world message
+ OMFactory factory = OMAbstractFactory.getOMFactory();
+ OMElement helloWorldElement = factory.createOMElement(HELLO_WORLD);
+
+ OMElement nameElement = factory.createOMElement(new QName("name"));
+ nameElement.setText("synapse");
+ OMElement versionElem = factory.createOMElement(new QName("version"));
+ versionElem.setText("3.1.0");
+ OMElement releaseDateElem = factory.createOMElement(new QName("release_date"));
+ releaseDateElem.setText("12/12/2010");
+
+ helloWorldElement.addChild(nameElement);
+ helloWorldElement.addChild(versionElem);
+ helloWorldElement.addChild(releaseDateElem);
+ this.helloWorld = helloWorldElement;
+ }
+
+ /**
+ * Returns the string value of the hello world message for the corresponding child
+ proeprty
+ * arguments are hello-world(name | version | release_date)
+ *
+ * @param context the context at the point in the expression when the function is called
+ * @param args arguments of the functions
+ * @return The string value of the property
+ * @throws org.jaxen.FunctionCallException
+ *
+ */
+ public Object call(Context context, List args) throws FunctionCallException {
+
+ if (synCtx == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Synapse message context has not been set for the " +
+ "XPath extension function 'synapse:hello-world(arg_name)'");
+ }
+ return null;
+ }
+
+ boolean traceOn = synCtx.getTracingState() == SynapseConstants.TRACING_ON;
+ boolean traceOrDebugOn = traceOn || log.isDebugEnabled();
+
+ if (args == null || args.size() == 0) {
+ if (traceOrDebugOn) {
+ traceOrDebug(traceOn, "argument key value for lookup is not specified");
+ }
+ return NULL_STRING;
+ } else
+ {
+ int size = args.size();
+ if (size == 1) {
+ String argument = StringFunction.evaluate(args.get(0), context.getNavigator());
+ if ("name".equals(argument) || "version".equals(argument) ||
+ "release_date".equals(argument)) {
+ return helloWorld.getFirstChildWithName(new QName(argument));
+ }else{
+ return helloWorld;
+ }
+ }
+ }
+ return NULL_STRING;
+ }
+
+ private void traceOrDebug(boolean traceOn, String msg) {
+ if (traceOn) {
+ trace.info(msg);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug(msg);
+ }
+ }
+
+ }
+ </pre>
+ <p>
+ Here we basically select an child element or the whole Hello World message based on the
+ aguments. Please refer to org.jaxen.Function for further details on the implementation.
+ With this extension in place synapse configuration can refer to a particular element of
+ our Hello World message with expression = "hello-world('name')" ,expression =
+ "hello-world('version')" , etc
+ </p>
+ <h4>
+ Registering Extensions
+ </h4>
+ <p>
+ We need one additional step to make all these extensions integrate into Synapse.
+ Registering extensions is done by declaring them in synapse.properties file.
+ synapse.properties can be found $SYNAPSE_HOME/repository/conf . Functions should be
+ declared under property synapse.xpath.func.extensions while Variables should be under
+ synapse.xpath.var.extensions .
+ </p>
+ <pre xml:space="preserve">
+ synapse.xpath.var.extensions=org.sample.HelloWorldXpathVariableResolver
+ synapse.xpath.func.extensions=org.sample. HelloWorldXpathFunctionProvider
+ </pre>
+ <p>
+ If multiple function / variable extesnions are needed comma delimited list can be
+ declared. Synapse at startup will register all these declared extensions (defined under
+ its CLASSPATH) and our HELLO-WORLD xpath extensions will be ready to roll.
+ </p>
+
+
+ </body>
</document>
\ No newline at end of file