I'm trying to deploy a Spring Boot Rest Controller on Tomcat 8. When I run it directly from Eclipse, it works fine. But when deploying it to Tomcat 8, I get a 404 error.
I've followed these instructions (https://www.baeldung.com/spring-boot-war-tomcat-deploy) and searched everywhere, but nothing seems to work.
Here is my Controller:
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class TomcatController {
#GetMapping("/hello")
public Collection<String> sayHello() {
return IntStream.range(0, 10)
.mapToObj(i -> "Hello number " + i)
.collect(Collectors.toList());
}
}
Here is my Application:
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 SsoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SsoApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SsoApplication.class);
}
}
And here 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>sso</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SSOServices</name>
<description>SSO Services</description>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/>
</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>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>${artifactId}</finalName>
</build>
</project>
Any help would be greatly appreciated.
To summarize, when I test through eclipse with "localhost:8080/hello", it works.
When I deploy to tomcat 8 and test with "localhost:8080/sso/hello", I get a 404.
From M. Deinum (above)
For Spring Boot 2.4 to work you would need to use Tomcat 8.5 as minimum (not just 8) or even better tomcat 9.
Related
I started learning Spring Framework and get this kind of error while running localhost:8080
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Controller.java
package com.springFramework.helloGame.controller;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class Controller {
#GetMapping("/sum")
public long displaySum(){
return 100;
}
}
HelloGameApplication.java
package com.springFramework.helloGame;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class HelloGameApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(HelloGameApplication.class, args);
}
}
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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springFramework</groupId>
<artifactId>helloGame</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloGame</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
my project structure looks fine, but don't know why I got error!
Please help me!
The Whitelabel page is a spring error handling method and it tries to hint to you that you do have a mapping for /error.
Now coming to the issue you need to write #RequestMapping("/") above your get mapping in the controller so that the spring knows the base URI.
It's an entry point for the spring application for the browser.
Now you have written /sum get URI and in the browser, you are trying for http://localhost:8080
So for the above Uri to work you need to provide #RequestMapping("/")
or you can use http://localhost:8080/sum with you current code.
It seems your controller only have a mapping for "/sum" path. Try querying localhost:8080/sum.
I'm going through this online course about Spring MVC.
During the course the instructor is adding a simple controller, and a simple jsp page.
In addition the application class is extending SpringBootServletInitializer.
my index.html file is found in src/main/webapp and my jsp file is found in src/main/webapp/WEB-INF/jsp
I've also added spring.mvc.view.prefix/suffix accordingly.
for some reason when i get to this point at the course, extending the SpringBootServletInitializer is causing whitelabel error to my main view (index.html) but the path to jsp file is working just fine.
I've tried some suggestions as changing #Controller to #RestController or removing the SpringBootServletInitializer but it didn't work (removing the SpringBootServletInitializer caused 404 when looking for the jsp page).
here is my code:
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.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.pluralSight</groupId>
<artifactId>conference</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>conference</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
controller:
package com.pluralSight.conference.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Map;
#Controller
public class GreetingController {
#GetMapping("greeting")
public String greeting(Map<String, Object> model){
model.put("message","Hello Daniel");
return "greeting";
}
}
application class:
package com.pluralSight.conference;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class ConferenceApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(ConferenceApplication.class, args);
}
}
application.properties:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
I have app with spring boot, i want to run this app with Java Application but when i call rest API it always response 404, but with Tomcat server it's ok. I don't know why
Here is my main app
package com.secret;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class SecretApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(SecretApplication.class, args);
}
}
here is my file 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.secret</groupId>
<artifactId>MySecret</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here is my controller
package com.secret.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.secret.common.dto.ResponseBodyDto;
#CrossOrigin
#RestController
#RequestMapping("/demo")
public class Demo {
#GetMapping(value = "/user")
public ResponseEntity<Object> getUserByUsername() throws Exception{
ResponseBodyDto<Object> dto = new ResponseBodyDto<>();
dto.setData("Ok");
return new ResponseEntity<Object>(dto, HttpStatus.OK);
}
}
And When i run my app by Java Application always get 404 when call rest API http://localhost:8080/MySecret/demo/user
{
"timestamp": "2020-05-28T08:03:05.090+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/MySecret/demo/user"
}
But when i run my app by Tomcat Server then it still success
{
"code": "R_200",
"message": "Your request has been processed successfully.",
"totalRecord": 0,
"data": "Ok"
}
I don't want to use Tomcat Server to run my app anymore, Someone help me pls!!!
When you run your project as jar (java application), you should use localhost:8080/demo/user
When you run your application into a server (jboss per example) the name of your war file is the root path.
localhost:8080/MySecret/demo/user
I think your war file is MySecret.war.
That's the reason of the difference between the first and the second. Since you don't have a base path, /demo/user is the path of your endpoint.
new to spring boot application development. I ran the application as java application and got the below error. THe application is deployed successfully , I don't know why this error is rendered ... beating my head.. thank you for your help in advance.
Whitelabel Error Page This application has no explicit mapping for
/error, so you are seeing this as a fallback. Sat Jul 13 21:37:31 IST
2019 There was an unexpected error (type=Not Found, status=404). No
message available
tried solutions given on stack overflow but no help. could you please help me if anywhere I do wrong here.
package com.cpi.poc.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cpi.poc.service.IService;
#RestController
#RequestMapping(value ="/test")
#ComponentScan(basePackages = "com.cgi.poc")
public class TestController {
#Autowired
IService service;
#RequestMapping(value = "/greet" , method = RequestMethod.GET)
public String testService(){
String result = service.greet();
return result;
}
}
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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.21.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cgi.poc</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>Demo project for Spring Boot</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-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Check whether you have class :
#SpringBootApplication
#ComponentScan("com.cgi.poc")
#ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
No need to put component scan on controller if you have the above class.
Verify by using lsof command that your java service is running on the port on not.
this application has no explicit mapping for /error
still displaying after making sure the main application is in the right package
made sure the application and service and controller are in right package tried using component scan as well as check dependancies
https://ibb.co/n7vhZLD : file/package order
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Dependacies
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</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.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<packaging>war</packaging>
Controller
import java.util.ArrayList;
import java.util.Hashtable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import model.Car;
import service.CarService;
#CrossOrigin
#RestController
#RequestMapping("/car")
public class CarController {
#Autowired
CarService cs;
#RequestMapping("/all")
public ArrayList<Car> getAll() {
return cs.getAll();
}
#RequestMapping("{id}")
public Car getCar(#PathVariable("id") String id) {
return cs.getCar(id);
}
}
Take a look at you package structure Main class DemoApplication is in com.example.demo package
package com.example.demo;
#SpringBootApplication
public class DemoApplication {
And CarService is in package service.CarService
import service.CarService;
#Autowired
CarService cs;
In the same way CarController might be in different package which are not in organised structure.
By default #SpringBootApplication perform component scan scanning from the package of the class that declares this annotation. Since your service and controller classes are not in sub packages of base package you need to explicitly add#ComponentScan
#SpringBootApplication
#ComponentScan({"service","controller"})
public class DemoApplication {