Yet another issue with deploying Spring Boot WAR to Tomcat... I have read the dozen of similar questions but have not found any fix for my issue.
I have a Spring Boot web app which is working fine when using the embedded tomcat web server (I can reach the index.html page using localhost:8080).
However when I deploy the WAR to Tomcat (the war is called ROOT.war so am I deploying the app at Tomcat's root), localhost:8080 returns 404. I need to call localhost:8080/index.html to get an answer. I just cannot figure out why!
pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>war</packaging>
<properties>
<java.version>11</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
...
</dependencies>
<build>
<finalName>ROOT</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.1</version>
<executions>
...
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Application.java
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I have one #RestController which does not override "/", and that's it.
In the generated WAR, the index.html is located at the top level (so same level as WEB-INF).
I also noticed that when Tomcat starts the web app, it prints:
INFO ServletWebServerApplicationContext ServletWebServerApplicationContext.prepareWebApplicationContext(ServletWebServerApplicationContext.java:292) [main] Root WebApplicationContext: initialization completed in 1674 ms
INFO WelcomePageHandlerMapping WelcomePageHandlerMapping.<init>(WelcomePageHandlerMapping.java:53) [main] Adding welcome page: ServletContext resource [/index.html]
I find the second line strange: it looks like Spring Boot is choosing to default back to a WelcomePageHandlerMapping instead of using the expected spring boot context. No idea where that comes from.
Maybe another indication: it does not print
Initializing Spring embedded WebApplicationContext
while this is printed when I start the app using the embedded Tomcat web server. But maybe it is fine if it is not there.
Tomcat version: 9.0.65
Tomcat config: default config: did not change anything there since installation.
Help!
I could reproduce!
With:
Dockerfile:
FROM tomcat:9.0.69-jre17-temurin-jammy
ARG WAR_FILE=target/ROOT.war
RUN addgroup --system tomcat \
&& adduser --system --ingroup tomcat tomcat \
&& chown -Rfh tomcat:tomcat $CATALINA_HOME
USER tomcat:tomcat
COPY ${WAR_FILE} $CATALINA_HOME/webapps/
CMD ["catalina.sh", "run"]
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>
<!-- max spring boot version for tomcat 9 (servlet-api): -->
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>traditional</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<!-- latest tomcat9 version, property controls spring dependency management: -->
<tomcat.version>9.0.69</tomcat.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-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>ROOT</finalName>
<!-- no spring-boot plugin!(?) -->
</build>
</project>
App/Entry:
package com.example.traditional;
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 TraditionalApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(TraditionalApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(TraditionalApplication.class);
}
}
(Some /custom controller, (mockMvc) tests)
and a "static index.html" in src/main/webapp (maven war default):
<html>
<body>
<h1>Hello</h1>
Hello World!
</body>
</html>
the (embedded tomcat) test succeeds:
#WebMvcTest
public class WebTest {
#Autowired
MockMvc mockMvc;
#Test
void testRoot() throws Exception {
mockMvc
.perform(
get("/")
).andExpectAll(
status().isOk(),
forwardedUrl("index.html")
);
} // ...
}
but after:
mvn clean install \
&& docker build -t my/tomcat9-app . \
&& docker run -p 8080:8080 my/tomcat9-app,
we get:
404 (tomcat error page) from http://localhost:8080
(http://localhost:8080/index.html, http://localhost:8080/custom work as expected ;(#
Simplest Solution
Move index.html from src/main/webapp to src/main/resources/static ! (stop running container, repeat mvn clean install && docker build ... && docker run);p #
Related
I have created a Spring Boot application. I use WildFly as the application server - this is what I want to use to run the application.
These are the Java and Maven related files I have:
#RestController
public class MyController {
#Autowired
private Student student;
#GetMapping(value="/index")
public String sayHello() {
return "Hello";
}
}
Of course I have the main method with the Spring Boot related annotations:
#SpringBootApplication
public class SpringBootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTestApplication.class, args);
}
}
I have the Maven file like this:
<?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.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.globalsoftwaresupport</groupId>
<artifactId>spring-boot-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<deploy.jboss.host>127.0.0.1</deploy.jboss.host>
<deploy.jboss.port>9990</deploy.jboss.port>
<deploy.jboss.username>balazs</deploy.jboss.username>
<deploy.jboss.password>balazs1990</deploy.jboss.password>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>2.0.2.Final</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<filename>${project.build.finalName}.war</filename>
<hostname>${deploy.jboss.host}</hostname>
<port>${deploy.jboss.port}</port>
<username>${deploy.jboss.username}</username>
<password>${deploy.jboss.password}</password>
</configuration>
</plugin>
</plugins>
</build>
<packaging>war</packaging>
When I build the project with mvn clean install then Maven compiles and deployed the app to the Wildfly server.
So far so good I have the application on the server. First of all:
1.) is it not a problem that I have the SNAPSHOT present in the context root?
2.) another problem is that I can not run the application - I start WildFly server in Eclipse and I check the context root.
Can you help me why is this happening? Thank you for your help in advance!
I have a project in spring boot reactive with webflux. Someone could tell me how to deploy it on Netty please?
Thanks
The Spring boot starter webflux has an embedded Netty so including this dependency in your project and declaring a class with a main method will launch your reactive web application in Netty.
For example if you use Maven add those dependencies :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
And then in your class containing the main method:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Or if you want a fresh start with everything already configured and ready to code : https://start.spring.io.
I am learning Spring Boot. I have just created my first project using maven, Spring Boot, Spring Rest support and MongoDB. It compiles successfully, but it resolves all the dependencies, but do not compile the java classes at all.
After compilation, jar file is correctly created, it contain lib folder, metadata etc, but it do not contain project class file at all.
Hence when i run the project with mvn spring-boot:run, it throws an exception that class not found (Main method class for Spring boot initialization).
Please suggest, what I am doing wrong here, here is my maven configuration class:
<?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>
<properties>
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.assignment.BootInitializer</start-class>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.9.RELEASE</version>
</parent>
<groupId>com.assignment</groupId>
<artifactId>spring-assignment</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And here is the main initializer class:
package com.assignment;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class BootInitializer {
public static void main(String[] args) {
SpringApplication.run(BootInitializer.class, args);
}
}
What I need to do, to ensure that maven is compiling the java classes and including them in the jar file.
Thanks.
I am learning Spring Boot.
Okay, good. Let's do one step at a time. Go to start.spring.io and generate a template project with whatever dependencies you want and whatever build tool (maven / gradle) you like. Build it and run it and see whether it is coming up or not. Then incrementally build on top of it.
I was trying to connect spring boot with jboss for a week... I read many topics on this forum and many of them are too old. I get error 404 every time when i want run server. Can you please help me to config my app with jboss properly?
UPDATE:
Thank you for help with error 404. I changed package to "war". But now when I run wildfly server Im getting error 403 (forbidden). I was looking how to fix it and still stay in the same place. It is so hard to get wildfly work with spring boot...
I updated files:
https://github.com/kuzyn007/LibraryCRUD
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>pl.seweryn</groupId>
<artifactId>LibraryCRUD</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<!-- Spring: boot starter parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<!-- Starter for building web, including RESTful, applications using Spring
MVC. Uses Tomcat as the default embedded container -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Starter for using Spring Data JPA with Hibernate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- Starter for testing Spring Boot applications with libraries including
JUnit, Hamcrest and Mockito -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- The spring-boot-devtools module can be included in any project to
provide additional development-time features. -->
<!-- Applications that use spring-boot-devtools will automatically restart
whenever files on the classpath change. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- JSP Standard Tag Library -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.servlet.jsp</groupId>
<artifactId>jboss-jsp-api_2.2_spec</artifactId>
<version>1.0.2.Final</version>
</dependency>
<!-- … -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- … -->
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<finalName>LibraryCRUD</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties
# MVC
spring.view.prefix=/WEB-INF/jsp/
spring.view.suffix=.jsp
# JNDI
spring.datasource.jndi-name=java:jboss/datasources/library
# JPA/HIBERNATE
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.naming.physical-strategy=pl.seweryn
spring.jpa.database=H2
spring.jpa.show-sql=true
Application.java
package pl.seweryn.init;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
//#Configuration
//#EnableAutoConfiguration
//#ComponentScan
#SpringBootApplication // same as #Configuration #EnableAutoConfiguration #ComponentScan - alternative
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Follow this instructions: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file
You basically have to package your app as a WAR and implement SpringBootServletInitializer.
I found many mistakes in my project and now its working. I will write here answer for my app.
Physical naming was wrong. It should be: spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl. Or I could delete this line and it will be provided default from spring boot
I have Application.class in pl.seweryn.init package. I added #ComponentScan(pl.seweryn)
BookDaoImpl was not a spring component. Added line #Component
I'm trying to run my Spring Boot application on a local Tomcat 8 server, but can't get it to run. It works fine in Eclipse and mvn spring-boot:run.
I added the SpringBootServletInitializer and changed the pom.xml as recommended. But it seems that it never runs.
Here is the main class:
#SpringBootApplication
public class SasuApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SasuApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SasuApplication.class, args);
}
}
And here is 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.sverin.poc</groupId>
<artifactId>sasu</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>sasu</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<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-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>sasu</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
What am I missing?
Old question I know, but I just had this problem with Spring Boot 2.0.3 and Tomcat 8.5. My solution was to remove the <absolute-ordering> element from my web.xml file.
Another reason could be Tomcat version.
Spring boot does not work with Tomcat 10 #22414
Perhaps the problem is in the Java version and environment variables...
check JRE_HOME, after I set to 1.8 it started working