问题
I'm trying to implement a custom mediator for WSO2 ESB (4.5.1) using its own XML configuration. I'm able to use the mediator just fine as a class mediator with the following config:
<class name="test.synapse.mediator.TestMediator"/>
However, what I'm trying to achieve is being able to call the mediator with a syntax like this:
<t:TestMediator xmlns:t="test:mediator" />
Having followed the available help on the matter for WSO2 ESB to the letter, I'm getting the following error as I try to create a proxy using the mediator with its own XML config:
ERROR - MediatorFactoryFinder Unknown mediator referenced by configuration element : {test:mediator}TestMediator
Needless to say, I've written the two text files containing the fully qualified class names of the mediator factory and serializer classes respectively and placed them in the META-INF/services
directory in the bundle jar file.
This is the source code for my mediator class:
package test.synapse.mediator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
public class TestMediator extends AbstractMediator {
public boolean mediate(MessageContext context) {
System.out.println("TestMediator mediating!");
return true;
}
}
Here's the code for my mediator factory:
package test.synapse.mediator;
import java.util.Properties;
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMElement;
import org.apache.synapse.Mediator;
import org.apache.synapse.config.xml.MediatorFactory;
public class TestMediatorFactory implements MediatorFactory {
public static final QName QNAME = new QName("test:mediator", "TestMediator");
@Override
public Mediator createMediator(OMElement omElement, Properties properties) {
return new TestMediator();
}
@Override
public QName getTagQName() {
return QNAME;
}
}
And the following is the code for my mediator serializer:
package test.synapse.mediator;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.synapse.Mediator;
import org.apache.synapse.config.xml.MediatorSerializer;
public class TestMediatorSerializer implements MediatorSerializer {
public static final String MEDIATOR_CLASS_NAME = TestMediator.class.getName();
@Override
public String getMediatorClassName() {
return MEDIATOR_CLASS_NAME;
}
@Override
public OMElement serializeMediator(OMElement parent, Mediator mediator) {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement element = factory.createOMElement(TestMediatorFactory.QNAME);
parent.addChild(element);
return element;
}
}
And finally, the somewhat lengthy content of the project's pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>test.synapse.mediator.TestMediator</groupId>
<artifactId>TestMediator</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<name>TestMediator</name>
<description>TestMediator</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>TestMediator</Bundle-SymbolicName>
<Bundle-Name>TestMediator</Bundle-Name>
<Bundle-ClassPath>.</Bundle-ClassPath>
<Export-Package>test.synapse.mediator</Export-Package>
<Import-Package>*; resolution:=optional</Import-Package>
<Fragment-Host>synapse-core</Fragment-Host>
</instructions>
</configuration>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<buildcommands>
<buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
</buildcommands>
<projectnatures>
<projectnature>org.wso2.developerstudio.eclipse.artifact.mediator.project.nature</projectnature>
<projectnature>org.eclipse.jdt.core.javanature</projectnature>
</projectnatures>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources/services</directory>
<targetPath>META-INF/services</targetPath>
</resource>
</resources>
</build>
<repositories>
<repository>
<releases>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<id>wso2-nexus</id>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<id>wso2-nexus</id>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1.0.wso2v2</version>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4.0.wso2v1</version>
</dependency>
<dependency>
<groupId>org.apache.synapse</groupId>
<artifactId>synapse-core</artifactId>
<version>2.1.0-wso2v7</version>
</dependency>
<dependency>
<groupId>wsdl4j.wso2</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2.wso2v4</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.schema.wso2</groupId>
<artifactId>XmlSchema</artifactId>
<version>1.4.7.wso2v2</version>
</dependency>
<dependency>
<groupId>org.apache.abdera.wso2</groupId>
<artifactId>abdera</artifactId>
<version>1.0.0.wso2v3</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs.wso2</groupId>
<artifactId>geronimo-stax-api_1.0_spec</artifactId>
<version>1.0.1.wso2v2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
<version>4.1.0-wso2v1</version>
</dependency>
<dependency>
<groupId>org.apache.neethi.wso2</groupId>
<artifactId>neethi</artifactId>
<version>2.0.4.wso2v4</version>
</dependency>
<dependency>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
<version>1.6.1.wso2v6</version>
</dependency>
<dependency>
<groupId>org.apache.woden.wso2</groupId>
<artifactId>woden</artifactId>
<version>1.0.0.M8-wso2v1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom.wso2</groupId>
<artifactId>axiom</artifactId>
<version>1.2.11.wso2v3</version>
</dependency>
<dependency>
<groupId>commons-io.wso2</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.0.wso2v2</version>
</dependency>
</dependencies>
<properties>
<CApp.type>lib/synapse/mediator</CApp.type>
</properties>
</project>
I've been experimenting for a long time changing various aspects of the pom-file and the code. I've come to notice, that I can call the mediator using the class-mediator if I leave out the Fragment-Host
part of the configuration. If the Fragment-Host
element is present, neither way of calling the mediator works.
As expected I'm using apache Maven to build a jar-file of the project. I'm dropping the jar to the <ESB_HOME>/repository/components/dropins
-directory.
I've tried using WSO2 ESB 4.5.1 and 4.7.0 with the exact same results.
What must I change to get the custom XML configuration to work?
Any input would be greatly appreciated!
Attachments:
Zipped source at Dropbox: TestMediator.zip
Jar built using maven at Dropbox: TestMediator-1.0.0.jar
回答1:
Seeing as there apparently is some bug in the WSO2 ESB itself, which causes the bundle containing the mediator and its factory and serializer not to get loaded in the case that its manifest contains a Fragment-Host
definition I went for a slightly more complicated scenario to get my mediator to function using custom XML config.
Having used an activator class in the bundle to confirm that it doesn't get loaded it occurred to me that I could also use the activator to manually register the MediatorFactory
and MediatorSerializer
classes in the ESB.
I did this by writing the following activator for my OSGI bundle:
package test;
import java.text.MessageFormat;
import java.util.Map;
import org.apache.synapse.config.xml.MediatorFactoryFinder;
import org.apache.synapse.config.xml.MediatorSerializer;
import org.apache.synapse.config.xml.MediatorSerializerFinder;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import test.synapse.mediator.TestMediator;
import test.synapse.mediator.TestMediatorFactory;
import test.synapse.mediator.TestMediatorSerializer;
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
{
Map<javax.xml.namespace.QName, java.lang.Class> mediatorFactoryMap = MediatorFactoryFinder.getInstance().getFactoryMap();
mediatorFactoryMap.put(TestMediatorFactory.QNAME, TestMediatorFactory.class);
}
{
Map<String, MediatorSerializer> mediatorSerializerMap = MediatorSerializerFinder.getInstance().getSerializerMap();
mediatorSerializerMap.put(TestMediator.class.getName(), TestMediatorSerializer.class.newInstance());
}
}
public void stop(BundleContext context) throws Exception {
// Maybe undo what was done in the start(BundleContext) method..?
System.out.println(this.getClass().getName() + ".stop(BundleContext) called");
}
}
Obviously the Activator class needs to be defined to be the activator for the bundle. This is done by adding the following node to the pom.xml bundle plugin configuration under the Instructions element:
<Bundle-Activator>test.Activator</Bundle-Activator>
Using this manual way of registering the factory and serializer classes the org.apache.synapse.config.xml.MediatorFactory
and org.apache.synapse.config.xml.MediatorSerializer
files are not needed and can be removed from the final jar.
Additionally the Fragment-Host
element needs to be removed from the same parent node to actually have the activator class' start method get called.
Also the osgi core dependency containing the BundleActivator
interface needs to be added.
By doing that we're left with the following complete pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>test.synapse.mediator.TestMediator</groupId>
<artifactId>TestMediator</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<name>TestMediator</name>
<description>TestMediator</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>TestMediator</Bundle-SymbolicName>
<Bundle-Name>TestMediator</Bundle-Name>
<Bundle-ClassPath>.</Bundle-ClassPath>
<Bundle-Activator>test.Activator</Bundle-Activator>
<Export-Package>test.synapse.mediator</Export-Package>
<Import-Package>*; resolution:=optional</Import-Package>
<!-- <Fragment-Host>synapse-core</Fragment-Host> -->
</instructions>
</configuration>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<buildcommands>
<buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
</buildcommands>
<projectnatures>
<projectnature>org.wso2.developerstudio.eclipse.artifact.mediator.project.nature</projectnature>
<projectnature>org.eclipse.jdt.core.javanature</projectnature>
</projectnatures>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<releases>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<id>wso2-nexus</id>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<id>wso2-nexus</id>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1.0.wso2v2</version>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4.0.wso2v1</version>
</dependency>
<dependency>
<groupId>org.apache.synapse</groupId>
<artifactId>synapse-core</artifactId>
<version>2.1.0-wso2v7</version>
</dependency>
<dependency>
<groupId>wsdl4j.wso2</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2.wso2v4</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.schema.wso2</groupId>
<artifactId>XmlSchema</artifactId>
<version>1.4.7.wso2v2</version>
</dependency>
<dependency>
<groupId>org.apache.abdera.wso2</groupId>
<artifactId>abdera</artifactId>
<version>1.0.0.wso2v3</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs.wso2</groupId>
<artifactId>geronimo-stax-api_1.0_spec</artifactId>
<version>1.0.1.wso2v2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
<version>4.1.0-wso2v1</version>
</dependency>
<dependency>
<groupId>org.apache.neethi.wso2</groupId>
<artifactId>neethi</artifactId>
<version>2.0.4.wso2v4</version>
</dependency>
<dependency>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
<version>1.6.1.wso2v6</version>
</dependency>
<dependency>
<groupId>org.apache.woden.wso2</groupId>
<artifactId>woden</artifactId>
<version>1.0.0.M8-wso2v1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom.wso2</groupId>
<artifactId>axiom</artifactId>
<version>1.2.11.wso2v3</version>
</dependency>
<dependency>
<groupId>commons-io.wso2</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.0.wso2v2</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>5.0.0</version>
</dependency>
</dependencies>
<properties>
<CApp.type>lib/synapse/mediator</CApp.type>
</properties>
</project>
Having done these modifications and dropping the Maven built jar to the /repository/components/dropins directory the mediator finally works with its custom configuration.
I've zipped the complete final project source code. That archive also is available on Dropbox: TestMediator-final.zip
Edit
Upon additional experimentation it became apparent that the above approach doesn't work in WSO2 ESB 4.5.1, which is the platform I was originally trying to get this to work on. The code performs as expected in WSO2 4.7.0.
I haven't been able to get WSO2 ESB 4.5.1 (or 4.6.0) to call the activator's start(BundleContext)
method no matter what I've tried.
来源:https://stackoverflow.com/questions/18675691/how-to-implement-a-custom-mediator-with-its-own-xml-configuration