ClassNotFoundException when running JUnit test in Maven - java

I'm currently trying to set up automated testing for a Maven project, but I've run into a problem. When running my tests using mvn test, I get the following result:
-------------------------------------------------------------------------------
Test set: no.digipat.patornat.servlets.ServletTests
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.398 s <<< FAILURE! - in no.digipat.patornat.servlets.ServletTests
no.digipat.patornat.servlets.ServletTests Time elapsed: 0.368 s <<< ERROR!
java.lang.NoClassDefFoundError: com/mongodb/OperationExecutor
Caused by: java.lang.ClassNotFoundException: com.mongodb.OperationExecutor
I get the same error when running the tests in Eclipse.
This is my pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>no.digipat.patornat</groupId>
<artifactId>backend</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Pat or Nat Backend</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<repositories>
<repository>
<id>cytomine-uliege-Cytomine-java-client</id>
<url>https://packagecloud.io/cytomine-uliege/Cytomine-java-client/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lordofthejars</groupId>
<artifactId>nosqlunit-mongodb</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>2.2.0-RC2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>be.cytomine.client</groupId>
<artifactId>cytomine-java-client</artifactId>
<version>2.0.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<includes>
<include>ServletTests.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>
The relevant Java files:
ServletTests.java:
package no.digipat.patornat.servlets;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import static com.lordofthejars.nosqlunit.mongodb.InMemoryMongoDb.InMemoryMongoRuleBuilder.newInMemoryMongoDbRule;
#RunWith(Suite.class)
#SuiteClasses({MyTest.class})
public class ServletTests {
private static final EnvironmentVariables environmentVariables = new EnvironmentVariables();
#ClassRule
public static final TestRule chain = RuleChain
.outerRule(newInMemoryMongoDbRule().build())
.around(environmentVariables);
#BeforeClass
public static void setUpClass() {
environmentVariables.set("MY_VARIABLE", "some value");
}
}
MyTest.java:
package no.digipat.patornat.servlets;
import static org.junit.Assert.*;
import org.junit.Test;
public class MyTest {
#Test
public void test() {
fail("Not yet implemented");
}
}
Any ideas on how to solve this? I tried running mvn clean (which previously helped me fix a similar issue), but to no avail.

I think you need the maven-compiler-plugin in your pom.xml
<build>
<!-- put here the path of your test source directory -->
<testSourceDirectory>src/test</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
...

It seems that the issue was that the latest versions of Fongo and mongo-java-driver are incompatible. When I change the dependencies of Fongo and/or the Mongo Java driver to older versions (I specifically tried versions 2.1.0 and 3.6.3, respectively), the error disappears. However, since this solution seems rather fragile and inflexible, the best bet is probably to switch to an alternative to Fongo. According to this GitHub comment, mongo-java-server could be a good option. A perhaps more robust alternative, and the one I'll probably end up using, is to use a "real" test database. This article has information about a couple of ways to do this.

Related

Intellij mvn install complains "cannot access <package>" during testComplile after adding cucumber-junit-platform-engine dependency in pom.xml

I am planning to use Cucumber Test with Junit 5 in Maven. So I followed cucumber to install different maven dependency. I added a runner class to execute my cucumber tests
package pirate;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
#Suite
#IncludeEngines("cucumber")
#SelectClasspathResource("pirate")
#ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "pirate")
public class Runner {}
I also created a new folder name pirate under resources folder and move all .feature files into that new folder.
But when I execute mvn clean install, the command fails at testCompile:
It seems like the compiler can't read the package name?
Below is my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>onetwothree</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>onetwothree</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<properties>
<configurationParameters>
cucumber.junit-platform.naming-strategy=long
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>7.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
My project structure is:
but if I comment out cucumber-junit-platform-engine dependency in pom.xml, the error is gone but it won't run the cucumber tests. Did I miss something here?
Not sure if it's related, but one of the error messages is like:
[ERROR] error reading /Users/xx/.m2/repository/org/junit/platform/junit-platform-engine/1.9.1/junit-platform-engine-1.9.1.jar; zip file is empty
[ERROR] /Users/xx/Desktop/zz/src/test/java/pirate/Runner.java:[1,1] cannot access pirate
ZipException opening "junit-platform-engine-1.9.1.jar": zip END header not found
Maven : error in opening zip file when running maven
following the procedure fixes the "cannot access " problem.
did you tried with a different scope than test for the cucumber-junit-platform-engine dependency?

Unit testing java maven

I have a maven project that looks like this:
If I run in the terminal:
mvn test
it will build the application and run the 3 tests:
SocialMultiplicationApplicationTests
MultiplicationServiceTest
RandomGeneratorServiceTest
but not RandomGeneratorServiceImplTest.
If I try to explicitly run this class:
mvn test -Dtest=RandomGeneratorServiceImplTest
I get:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test)
on project social-multiplication: No tests were executed! (Set -DfailIfNoTests=false to ignore this error.) -> [Help 1]
Here's my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>microservices.book</groupId>
<artifactId>social-multiplication</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>social-multiplication</name>
<description>Social Multiplication App</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here's the test class that won't run:
package microservices.book.multiplication.service;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class RandomGeneratorServiceImplTest {
private RandomGeneratorServiceImpl randomGeneratorServiceImp;
#Before
public void setUp(){
randomGeneratorServiceImp = new RandomGeneratorServiceImpl();
}
#Test
public void generateRandomFactorIsBetweenExpectedLimits() {
List<Integer> randomFactors = IntStream.range(0,1000)
.map(i -> randomGeneratorServiceImp.generateRandomFactor())
.boxed()
.collect(Collectors.toList());
for(Integer i: randomFactors){
assertThat(i).isIn(
IntStream.range(11, 100).
boxed().collect(Collectors.toList()));
}
}
}
EDIT: SOLUTION
The proble was indeed the conflict between junit4 and junit5.
I chose to move my tests to junit5, hence I replaced #Before with #BeforeAll and added #TestInstance(Lifecycle.PER_CLASS) on top of the RandomGeneratorServiceImplTest class definition.
Couple links I found useful:
junit docs
differences between junit4 and junit5
The reason lies in mixing JUnit 5 and JUnit 4.
The maven-surefire-plugin picks only one strategy to execute tests and favors JUnit 5 in this case.
Either replace the dependency to junit by junit-vintage-engine:
<!-- <dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
Or adapt your tests to use JUnit 5 instead (as for example in RandomGeneratorServiceImplTest):
...
//import org.junit.Before;
//import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
...
public class RandomGeneratorServiceImplTest {
...
// #Before
#BeforeEach
public void setUp(){
...
}
// #Test can stay as is, only import needs to be updated
#Test
public void generateRandomFactorIsBetweenExpectedLimits() {
...
}
}
Try adding this plugin to your build section in pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>

Junit with maven program is not working

When i run this i am getting Initialization error and there is no console error.
I have attached my junit test code and pom.xml code. please help me with the solution. And its a Maven project.
Junit program:
import static org.junit.Assert.*;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
public class JunitTest {
#Test
public void test() {
// fail("Not yet implemented");
System.out.println("Junit code");
WebDriver driver = new ChromeDriver();
driver.get("https://www.amazon.in/");
Select s = new Select(driver.findElement(By.id("searchDropdownBox")));
s.selectByVisibleText("Books");
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("harry potter");
}
}
Pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.testmaven</groupId>
<artifactId>mavenDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
</project>
You need to define a build phase in POM for doing the compilation of integrated unit tests.
add this code snippet in pom.xml for running the test classes.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You can find more information on:
http://maven.apache.org/surefire/maven-failsafe-plugin/usage.html

Maven Surefire plugin did not rerun failed Cucumber tests

I am using the Java implementation of Selenium WebDriver (version 2.53.0) to run some automated tests against a web application. The tests are written in Behaviour Driven Testing format using the Java implementation of Cucumber (version 1.2.3). I use Maven (version 3.3.9) to import all my dependencies and also to build and run the tests. The tests are organised into different categories using Cucumber tags. For example, I can run one category of tests tagged with #JohnnyBravo from the command line using the following commands:
cd path_to_Maven_POM_file
mvn clean test -Dcucumber.options="--tags #JohnnyBravo"
After doing some research, I found out that you can use the Maven SureFire plugin to rerun failed tests by adding "-Dsurefire.rerunFailingTestsCount=2" to the Maven command above according to this link. I then tried to rerun that category of tests using the command below while ensuring that some of them will definitely fail so as to see if they will be rerun or not:
mvn clean test -Dcucumber.options="--tags #JohnnyBravo" -Dsurefire.rerunFailingTestsCount=2
Unfortunately, the failed tests did not rerun. What am I doing wrong here ?
My POM file is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>regression-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<cucumber.version>1.2.3</cucumber.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>com.vimalselvam</groupId>
<artifactId>cucumber-extentsreport</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.pojosontheweb</groupId>
<artifactId>monte-repack</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<systemPropertyVariables>
<webdriver.chrome.driver>src/test/resources/chromedriver/chromedriver.exe</webdriver.chrome.driver>
</systemPropertyVariables>
<!--<testFailureIgnore>true</testFailureIgnore>-->
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
The Cucumber JUnit test runner class is shown below:
import com.cucumber.listener.ExtentCucumberFormatter;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.HashMap;
#RunWith(Cucumber.class)
#CucumberOptions(
monochrome = false,
plugin = {
"pretty",
"html:C:/Test_Output_Data/Results/HTML/",
"json:C:/Test_Output_Data/Results/results.json",
"com.cucumber.listener.ExtentCucumberFormatter"
},
features = {"src/test/resources/"},
tags = {
"#JohnnyBravo",
//"#AgentUI", "#Smoke",
//"#GenUI", "#Smoke",
//"#GenUI", "#Regression",
}
)
public class GeneralRunnerTest {
#BeforeClass
public static void setup() {
ExtentCucumberFormatter.initiateExtentCucumberFormatter();
ExtentCucumberFormatter.loadConfig(new File("src/test/resources/extent-config.xml"));
ExtentCucumberFormatter.addSystemInfo("Browser Name", "Firefox");
ExtentCucumberFormatter.addSystemInfo("Browser version", "46.0.1");
ExtentCucumberFormatter.addSystemInfo("Selenium version", "2.53.0");
HashMap<String, String> systemInfo = new HashMap<>();
systemInfo.put("Cucumber Version", "1.2.3");
systemInfo.put("Extent Cucumber Reporter Version", "1.1.0");
ExtentCucumberFormatter.addSystemInfo(systemInfo);
}
}
Check if you are using the right version for your cucumber dependencies.
On the page for this feature on the surefire website, it says
Since of 2.21.0 the provider surefire-junit47 can rerun scenarios created by cucumber-jvm 2.0.0 and higher.
Also check if you're using the same junit provider that they've mentioned. I'm not sure which is the default provider.

How to implement a custom mediator with its own XML configuration?

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
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.

Categories