I'm trying to learn Java and I've done a Springboot application using Eclipse and Maven. I started downloading the base from https://start.spring.io/ and then I created my first controller and jsp index page. But when I try to package it in war and publish it on AWS elasticbeanstalk I had this error:
Sat Oct 05 09:42:45 UTC 2019
There was an unexpected error (type=Not Found, status=404).
/WEB-INF/jsp/index.jsp
I state that:
- When I run the web app on my computer it works perfectly!
- I've already set on AWS (in the custom variables) to change the port on 5000
This is the project structure
portfolio
- src
- main
- java
- resources (where i have static and application.properties
- webapp
- WEB-INF
- jsp
- index.jsp
pom.xml
This is the pom.xml
<?xml version="1.0" encoding="UTF-8"?>
https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
war
org.springframework.boot
spring-boot-starter-parent
2.1.9.RELEASE
com.sofidis
portfolio
0.0.1-SNAPSHOT
portfolio
Portfolio project for Spring Boot
<properties>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>9.0.26</version>
<!-- aggiunto per creare il war -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<!-- plugin repository aggiunto per compilare il war -->
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<!-- precedente <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin> -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This is the application.properties
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
This is my the main controller PortfolioApplication.java
package com.sofidis.portfolio;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class PortfolioApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PortfolioApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(PortfolioApplication.class);
}
}
This is my HomeController
import com.sofidis.portfolio.model.*;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController
{
#RequestMapping(value = "/")
public String index( HttpSession session)
{
PageMeta ptitle = new PageMeta();
String titlepagina= ptitle.getPtitle("index");
session.setAttribute("pagetitle", titlepagina);
PageMeta pdesc = new PageMeta();
String descpagina= pdesc.getPdescription("index");
session.setAttribute("pagedescription", descpagina);
return "index";
}
}
And this is the index.jps
<%# page isELIgnored="false"%>
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>${pagetitle}</title>
<meta name="description" content="${pagedescription}">
<jsp:include page="./includes/common_head.jsp" />
</head>
<body>
<p>Hello World</p>
</body>
</html>
Thank you very much for help!! I'm desperate :((
Under WEB-INF you should only place classes, libraries, web.xml. The JSPs should be placed on the same level as WEB-INF, not under WEB-INF. In your case it should be as follows:
webapp
WEB-INF
...
jsp
index.jsp
Afterwards there can also other problems. But first change the structure.
Related
I trying to build a simple welcome page (in jsp) using Spring Boot.
Below is the project structure
Application
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
APIController
#Controller
public class APIController {
#RequestMapping("/")
public String home() {
System.out.println("testing");
return "welcome";
}
}
When I access http://localhost:8080/, I get below error
This application has no explicit mapping for /error, so you are seeing
this as a fallback.
Wed May 23 15:31:51 MYT 2018 There was an unexpected error (type=Not
Found, status=404). No message available
By curl
{"timestamp":1527061233703,"status":404,"error":"Not Found","message":"No message available","path":"/"}
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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-web-jsp</artifactId>
<packaging>war</packaging>
<name>Spring Boot Web JSP Example</name>
<description>Spring Boot Web JSP Example</description>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- This is a web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Optional, test for static content, bootstrap CSS-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Package as an executable jar/war -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
You have to define the prefix and suffix for you jsp file in application.properties file like following:
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
In directory \src\main\resources\static, Create a simple index.html file
<html>
<head>Hello, Bich Van</head>
<body>
<h3>Today is a rainny day</h3>
</body>
</html>
Then try again at http://localhost:8080
If you don't like static HTML files, you can use JSP, but need a little complicate. You need declaring JSP View resolver in Spring MVC configuration.
Reference document: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-welcome-page
Ensure that you have jasper and jstl in the list of dependencies:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Here is a working starter project - https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-jsp
It's better to use thymeleaf in your spring boot project and add the following dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
In directory \src\main\resources\template, Create a simple index.html file
i 'm new in spring boot and i wanted to start with a simple example however nothing seemed to work
this my controller:
Package controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class testController {
RequestMapping("view/aboutus")
public String greeting(Model model) {
model.addAttribute("name", "azertyyyy");
return "aboutus"; }}
and this is the jsp view:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE>
<html> <body> ${name}
<p>hello world</p> </body></html>
i added the needed dependencies:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
and i added the prefix and suffix in application.properties
when i run the application only hello world is shown on the view without the name variable, after searching here i changed the view directory from src/main/webapp/view to src/main/resource/templates but spring boot couldn't find the view anymore
I am not sure if you are fully aware of the changes we have to make when we want to run the application as war package.
Change the packing to war from jar and require dependencies.
Change the main application class to extend SpringBootServletInitializer and implement configure()
Define your jsp pages path in application properties
Put JSPs in correct path (webapp/WEB-INF/jsp check screen shot)
Directory Structure for the project
Following is the code changes I have to done to run the JSP
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>Test_Exception_Framework</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Test_Exception_Framework</name>
<description>Project to test ExceptionFramework</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Need this to compile JSP -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.6.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Main Class
package com.exception;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
#SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBootWebApplication.class);
}
}
Rest Controller - which redirects to JSP
package com.exception.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(method = RequestMethod.GET)
public class TestExceptionController {
#RequestMapping("/")
public String welcome(Map<String, Object> model) {
System.out.println("in controller");
model.put("message", "hello spring boot");
return "welcome";
}
}
application.properties - define the path for JSPs
server.port=8085
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
1)*** use spring version 2.0.3.RELEASE or less
2) add the dependency
<!-- Need this to compile JSP -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
3) this optional dependency
<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
I am trying to deploy a spring boot application as a WAR to a tomcat server. I can build and deploy the war to the tomcat server just fine. When I start the server though my spring application never runs. The server starts up just fine. I have done everything Spring says to do here,
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file
My project has its own custom Parent POM and consists of 2 modules.
I have read several other similar threads and as far as I can tell I have everything set up properly but clearly something is wrong. Any help would be much appreciated.
THank You!
Parent pom
<groupId>com.project</groupId>
<artifactId>TelematicsNotificationSystem</artifactId>
<name>TelematicsNotificationSystem</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<artifact-deployer.version>2.0.0-RELEASE</artifact-deployer.version>
<cxf.version>2.5.2</cxf.version>
<start-class>com.project.TNS.TelematicsNotificationSystem</start-class>
</properties>
<modules>
<module>TelematicsNotificationSystem-wsclient</module>
<module>TelematicsNotificationSystem-web</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
</dependencies>
Web Project Pom
<artifactId>TelematicsNotificationSystem-Web</artifactId>
<name>TelematicsNotificationSystem-Web</name>
<packaging>war</packaging>
<parent>
<groupId>com.project</groupId>
<artifactId>TelematicsNotificationSystem</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<start-class>com.project.TNS.TelematicsNotificationSystem</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
My Application Class
package TNS;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
#SpringBootApplication
public class TelematicsNotificationSystem extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(TelematicsNotificationSystem.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TelematicsNotificationSystem.class);
}
}
Remember to refresh the application once deployed in Tomcat. It may be working well and only a refresh is needed.
Although I agree with Deinum that I needed to clean up my Pom that was not the overall fix. The fix was to simply add a component scan to my class which contained my main method.
#SpringBootApplication
#ComponentScan(basePackageClasses = DashBoardController.class)
public class TelematicsNotificationSystem extends SpringBootServletInitializer
The starting app couldn't find the Controller so it could handle any of my mapping requests.
it appears that the GA versions of
spring-core
spring-data-commons
spring-data-mongodb
as well as the most recent release candidate of
spring-boot-starter-web
spring-boot-autoconfigure
are not compatible.
what versions of these artifacts are compatible with each other?
I have a very basic Application.java that puts two objects into a MongoDB database and then takes them out and prints them to the screen.
import game.acorn.entities.Entity;
import game.acorn.mRepositoryInterfaces.EntityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application implements CommandLineRunner{
#Autowired
private EntityRepository repository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public void run(String... args) throws Exception {
repository.deleteAll();
repository.save(new Entity("Jack", "Skellington"));
repository.save(new Entity("Blake", "Yarbrough"));
System.out.println("Entities found");
for (Entity entity : repository.findAll()){
System.out.println(entity);
}
System.out.println();
System.out.println("Entity by first name 'Jack'");
System.out.println(repository.findByFirstName("Jack"));
System.out.println();
System.out.println("Entity by first name 'Blake'");
System.out.println(repository.findByFirstName("Blake"));
}
}
When I run this application with
spring-core version 4.0.2.RELEASE
spring-data-commons version 1.5.0.RELEASE
spring-boot-starter-web version 1.0.0.RC4
spring-data-mongodb version 1.4.1.RELEASE
spring-boot-autoconfigure version 1.0.0.RC3
I end up getting a java.lang.NoClassDefFoundError at
org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport.registerBeanDefinitions
which looks like
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
final BeanDefinitionRegistry registry) {
new RepositoryConfigurationDelegate(getConfigurationSource(), this.resourceLoader)
.registerRepositoriesIn(registry, getRepositoryConfigurationExtension());
}
with
new RepositoryConfigurationDelegate(getConfigurationSource(), this.resourceLoader)
being the line 58. It seems that there is a discrepancy between the version I am using and spring-boot's dependency.
So I try to up version my spring-data-commons to version 1.7.0.RELEASE
and then the class becomes available but I then get a java.lang.NoSuchMethodError at
org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport$1.<init>(AbstractRepositoryConfigurationSourceSupport.java:66)
which looks like
private AnnotationRepositoryConfigurationSource getConfigurationSource() {
StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(
getConfiguration(), true);
return new AnnotationRepositoryConfigurationSource(metadata, getAnnotation(),
this.environment) {
#Override
public java.lang.Iterable<String> getBasePackages() {
return AbstractRepositoryConfigurationSourceSupport.this
.getBasePackages();
};
};
}
with
return new AnnotationRepositoryConfigurationSource(metadata, getAnnotation(),
this.environment) {
being lines 65-66.
when I check out
org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource
I find that the constructor
public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class<? extends Annotation> annotation,
ResourceLoader resourceLoader, Environment environment) {
super(environment);
Assert.notNull(metadata);
Assert.notNull(annotation);
Assert.notNull(resourceLoader);
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(annotation.getName()));
this.metadata = metadata;
this.resourceLoader = resourceLoader;
}
expects one more argument than AbstractRepositoryConfigurationSourceSupport in spring-boot-autoconfigure gives it.
So, my question is, what versions of
spring-core
spring-data-commons
spring-boot-starter-web
spring-data-mongodb
spring-boot-autoconfigure
are compatible with each other?
my pom looks like
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RC3</version>
</parent>
<groupId>Master-Project</groupId>
<artifactId>Master-Project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Master Project for MongoDB and Spring</description>
<modules>
</modules>
<dependencies>
<!-- Spring Stuff -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.4.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.0.0.RC3</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<!--
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.3</source>
<target>1.1</target>
</configuration>
</plugin>
-->
<plugin>
<groupId>org.apache.maven.plugin</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
</project>
When I remove the version tags on the dependencies I get the same no such method exception.
This is fixed if you use the Spring Boot dependencies pom (or the starter parent) with 1.0.0.RC5 or better.
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.