I have this test project I created, composed out of 2 projects: one using spring-boot and one using spring-mvc. Each one of them works fine standalone. What I want to do is to run the spring-boot and be able to access the web pages of the spring-mvc project by loading its context. The project is quite simple as I just want to test how to do the mix.
The problem is that when I am running the spring-boot application, the page from spring-mvc is not accessible, as it does not add the webbapp folder (containing WEB-INF) in the build. I am able to autowire the service from spring-mvc inside the spring-boot application.
The tree looks as follows:
The Application.java class for spring-boot is the following:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import java.util.Arrays;
@SpringBootApplication
@ComponentScan({"org.burdu", "hello"})
//@ImportResource({"classpath:WEB-INF/spring-core-config.xml", "classpath:WEB-INF/spring-mvc-config.xml"})
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
The root build.gradle
group 'net.burdu'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'idea'
sourceCompatibility = 1.8
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}
root settings.gradle
rootProject.name = 'testSpringXMLAndBoot'
include 'spring-mvc'
include 'spring-boot'
spring-boot build.gradle
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
apply plugin: 'spring-boot'
sourceCompatibility = 1.8
repositories {
jcenter()
mavenCentral()
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
}
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile project(':spring-mvc')
}
spring-mvc build.gradle
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
apply plugin: 'jetty'
sourceCompatibility = 1.8
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'org.springframework:spring-webmvc:4.1.6.RELEASE'
compile 'javax.servlet:jstl:1.2'
}
jettyRun{
contextPath = ""
httpPort = 8080
}
jettyRunWar{
contextPath = ""
httpPort = 8080
}
spring-core-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:component-scan base-package="org.burdu.web" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
</beans>
spring-mvc-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:component-scan base-package="org.burdu.service" />
</beans>
web.xml inside spring-mvc project
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Gradle + Spring MVC Hello World + XML</display-name>
<description>Spring MVC web application</description>
<!-- For web context -->
<servlet>
<servlet-name>hello-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- For root context -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-core-config.xml</param-value>
</context-param>
</web-app>
The HelloController inside spring-boot, HelloWorldService and WelcomeController are simple beans. I am not pasting their content here since the question already got too long, but if needed I can add them.
I've imported the combined projects into my IDE and I found it's hard to integrate two projects into one and keep them original. The real difficulty is spring could not known the resources inside jar of sub-project spring-mvc
located in lib/spring-mvc.jar
. If I extract it into sub-project spring-boot
, it still doesn't work.
Afterwards, I found this documentation about JSP limitations
in spring-boot, which says:
An executable jar will not work because of a hard coded file pattern in Tomcat
What's more, my suggest is to convert your application into modern spring-boot form as following:
Convert an existing application to Spring Boot
In this case, you just need convert your servlets and filters defined in web.xml
into spring beans as documentation said. Additionally, spring-core-config.xml
and spring-mvc-config.xml
can keep no change cause they can be imported directly even though they are in embeded jar. It should be easy.
After you converting your application into spring boot, you can take all control over the web container too.
At the end, if you are really want to use them together, following documentation could be useful:
Deploying a WAR in an Old (Servlet 2.5) Container
This time, you can specify SpringBootContextLoaderListener
as your listener at your web.xml
. It could help to configure your application. However, as what spring says, it's only useful for deploying your application into old container.
But, if I were you, I will convert it to spring-boot format. Cause it can simplify maintenance work.
By default, spring boot only allowed directories /
,META-INF/resources
,resources
,public
,static
as resources loading path. From this prospective, if all your resources are located under these directories it should work. Of course, specifying document root would be required. If you can tolerant extracting spring-mvc
, I think this would be the solution.
If spring context defined in embedded jar is what you want, you can just add a star after classpath
such as classpath*:WEB-INF/applicationContext.xml
. This will add any WEB-INF/applicationContext.xml
in any lib jar. In other words, you only need add a star after classpath
at your @ImportResource
expression. If all things' going well, you are there.
I tried these small changes to your github project:
spring-boot/build.gradle:
// This will include files and settings from spring-mvc
war {
baseName = 'testSpringXMLAndBoot'
version = '0.1.0'
from '../spring-mvc/src/main/webapp'
}
// tomcat-embed-jasper is for jsp support
dependencies {
..
compile("org.apache.tomcat.embed:tomcat-embed-jasper")
..
}
spring-boot/src/main/java/hello/Application.java:
@SpringBootApplication
@ComponentScan({"org.burdu", "hello"})
@ImportResource({"classpath:WEB-INF/spring-mvc-config.xml"}) // added this resource back
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
..
}
}
Now running:
Will still run standalone spring-mvc
module on Jetty server
And running:
Will include spring-mvc
context to spring-boot
and run them on an embedded Tomcat.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With