| <!-- |
| ~ Licensed to the Apache Software Foundation (ASF) under one |
| ~ or more contributor license agreements. See the NOTICE file |
| ~ distributed with this work for additional information |
| ~ regarding copyright ownership. The ASF licenses this file |
| ~ to you under the Apache License, Version 2.0 (the |
| ~ "License"); you may not use this file except in compliance |
| ~ with the License. You may obtain a copy of the License at |
| ~ |
| ~ http://www.apache.org/licenses/LICENSE-2.0 |
| ~ |
| ~ Unless required by applicable law or agreed to in writing, |
| ~ software distributed under the License is distributed on an |
| ~ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| ~ KIND, either express or implied. See the License for the |
| ~ specific language governing permissions and limitations |
| ~ under the License. |
| --> |
| <html> |
| <head> |
| <meta content="text/html; charset=iso-8859-1" http-equiv="content-type"> |
| <title>Extending Synapse</title> |
| </head> |
| |
| <body> |
| <h1>Extending Synapse<br> |
| </h1> |
| <br> |
| |
| |
| <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 SynapseEnvironments to be used. The |
| SynapseConfiguration holds the global configuration model that defines |
| message mediation rules and common definitions to be used, while the |
| environment gives access to the underlying SOAP implementation used. A |
| typical mediator would need to manipulate the MessageContext by referring to |
| the SynapseConfiguration. However it is strongly recommended that the |
| SynapseConfiguration should not be 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 custom named properties |
| into the MessageContext for later retrieval by successive mediators.<br> |
| </p> |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/MessageContext.java?view=markup">MessageContext |
| Interface</a></h4> |
| |
| <p></p> |
| <pre>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 <a>MessageContext</a> |
| interface, and uses the Axis2 <a>EndpointReference</a> and SOAPEnvelope |
| classes/interfaces.</p> |
| |
| <p>The purpose of this interface is to capture a message as it flows through |
| the system. As you will see the messages are represented using the SOAP |
| infoset. Binary messages can be embedded in the Envelope using the MTOM |
| support built into Axis2's AXIOM object model.</p> |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/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>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 <a>SynapseMessage</a> 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> |
| Mediators may be Node mediators (i.e. these contain sub mediators) or Leaf |
| mediators (mediators that does not hold any sub mediators). A Node mediator |
| must implement the org.apache.synapse.api.ListMediator interface listed |
| below, or extend from the org.apache.synapse.mediators.AbstractListMediator. |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/ListMediator.java?view=markup">The |
| ListMediator interface</a></h4> |
| <pre>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> |
| 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. |
| Mediator instance which performs filtering should implement the |
| FilterMediator interface. |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/FilterMediator.java?view=markup">FilterMediator |
| interface</a></h4> |
| <pre>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> |
| 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 a text file by the name |
| "org.apache.synapse.config.xml.MediatorFactory" which will contain the fully |
| qualified name(s) of your MediatorFactory implementation class(es). 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. |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactory.java?view=markup">The |
| MediatorFactory interface</a></h4> |
| <pre>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></p> |
| |
| <h4><a |
| href="http://svn.apache.org/viewvc/webservices/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorSerializer.java?view=markup">The |
| MediatorSerializer interface</a></h4> |
| <pre>/**</pre> |
| <pre>* Interface which should be implemented by mediator serializers. Does the</pre> |
| <pre>* reverse of the MediatorFactory</pre> |
| <pre>*/</pre> |
| <pre>public interface MediatorSerializer {</pre> |
| <pre></pre> |
| <pre> /**</pre> |
| <pre> * Return the XML representation of this mediator</pre> |
| <pre> * @param m mediator to be serialized</pre> |
| <pre> * @param parent the OMElement to which the serialization should be attached</pre> |
| <pre> * @return the serialized mediator XML</pre> |
| <pre> */</pre> |
| <pre> public OMElement serializeMediator(OMElement parent, Mediator m);</pre> |
| <pre></pre> |
| <pre> /**</pre> |
| <pre> * Return the class name of the mediator which can be serialized</pre> |
| <pre> * @return the class name</pre> |
| <pre> */</pre> |
| <pre> public String getMediatorClassName();</pre> |
| <pre>}</pre> |
| |
| <h2>Configuring mediators</h2> |
| Mediators could access properties defined into the Synapse configuration to |
| configure the local behaviour. Refer to the Spring mediator and Script |
| mediator implementations for examples on how this could be achieved. |
| |
| <h4>Loading of Extensions by the Synapse runtime</h4> |
| 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.ExtensionFactory 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 |
| <pre>synapse-extensions.jar |
| /META-INF/services |
| org.apache.synapse.config.xml.ExtensionFactory |
| org.apache.synapse.config.xml.MediatorFactory |
| /... the implementation classes as usual...</pre> |
| </body> |
| </html> |