| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <!-- |
| ~ 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. |
| --> |
| |
| <document> |
| <properties> |
| <title>Apache Synapse - Extending Synapse</title> |
| </properties> |
| <body> |
| <div id="contentBox"> |
| <section name="Apache Synapse ESB - Extending Synapse"> |
| <p> |
| Apache Synapse provides a number of extension points so that |
| users can plug-in custom developed code to extend the |
| functionality of the ESB. While the built-in mediators are sufficient to implement |
| most integration scenarios, sometimes it is very helpful to be able to deploy some custom code into the |
| service bus and make the solution simpler. Most Synapse APIs are in Java and |
| therefore the users looking to extend Synapse are expected to have a |
| decent knowledge and experience in Java programming. |
| </p> |
| </section> |
| <section name="Writing custom Mediator implementations"> |
| |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">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()... |
| |
| }</div> |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">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(); |
| }</div> |
| <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 rocess the message |
| onwards. |
| </p> |
| </section> |
| |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">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(); |
| }</div> |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">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); |
| }</div> |
| </div> |
| <section name="Writing custom Configuration implementations for mediators"> |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">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(); |
| }</div> |
| <h4> |
| <a class="externalLink" |
| 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> |
| <div class="xmlConf">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(); |
| }</div> |
| </section> |
| <section name="Configuring mediators"> |
| <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 class="externalLink" |
| 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> |
| <div class="xmlConf">synapse-extensions.jar |
| /META-INF/services |
| org.apache.synapse.config.xml.MediatorFactory |
| org.apache.synapse.config.xml.MediatorSerializer |
| /... the implementation classes as usual...</div> |
| </section> |
| |
| |
| <section name="Writing Synapse Observers"> |
| <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> |
| <div class="xmlConf"> 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);</div> |
| <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> |
| <div class="xmlConf">synapse.observers=test.LoggingObserverImpl, test.SimpleObserverImpl</div> |
| </section> |
| |
| <section name="Scheduled Tasks"> |
| <p> |
| A scheduled task is a custom developed piece of Java code that |
| is scheduled in the ESB to execute periodically. A scheduled task |
| must implement the org.apache.synapse.task.Task |
| interface. This interface has a single 'execute' method. Once scheduled the |
| execute method is called by Synapse periodically. |
| </p> |
| <p> |
| Synapse also comes with a built-in task implementation known as |
| the MessageInjector.This task can be used to inject messages into |
| the service bus periodically. Refer sample 300 to see how to use the |
| MessageInjector task. |
| </p> |
| </section> |
| </body> |
| </document> |