How to create executable WAR or JAR in Springboot - java

I wrote a simple HELLOWORLD Springboot/thymeleaf project in eclipse and I can run it.
Then I tried to create a single executable war (or jar) file, but it is not possible. What I need is a single executable Jar or war file that I use as a executable (runnable) file on my computer without using eclipse.
Export as a War
Export as a Jar
application class:
package com.example.handlingformsubmission;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class HandlingFormSubmissionApplication {
public static void main(String[] args) {
SpringApplication.run(HandlingFormSubmissionApplication.class, args);
}
}
The Controller ->
package com.example.handlingformsubmission;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
#Controller
public class GreetingController {
#GetMapping("/greeting")
public String greetingForm(Model model) {
model.addAttribute("greeting", new Greeting());
return "greeting";
}
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting, Model model) {
model.addAttribute("greeting", greeting);
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 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.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>handling-form-submission</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>handling-form-submission</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-thymeleaf</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
http file:
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Form</h1>
<form action="#" th:action="#{/greeting}" th:object="${greeting}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>

I found the solution:
1- Add this code in pom file:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2- Then run the project as a MAVEN BUILD.
3- write "package" in goals field.
4- click run.

Related

Spring Boot jsp file not found Error 404 weird prefix

I am currently learning Spring/Spring Boot and I am trying to code a forgot password function. All my other functions, like login etc. are working as intended, but redirecting to an reset-password page does not work for some reason and gives me the following error, in which it looks for the jsp with a weird prefix.
There was an unexpected error (type=Not Found, status=404).
JSP file [/reset-password/WEB-INF/jsp/reset-password.jsp] not found
My folder structure
I generate links that look like so: http://localhost:8080/reset-password/{a-random-uuid}
reset-password.jsp
<%# include file="includes/header.jsp" %>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Reset your password</h3>
</div>
<div class="panel-body">
<form:form modelAttribute="resetPasswordForm" role="form">
<form:errors cssClass="error" />
<div class="form-group">
<form:label path="password">Type new password</form:label>
<form:password path="password" class="form-control"
placeholder="Password" />
<form:errors cssClass="error" path="password" />
</div>
<div class="form-group">
<form:label path="retypePassword">Retype new password</form:label>
<form:password path="retypePassword" class="form-control"
placeholder="Retype password" />
<form:errors cssClass="error" path="retypePassword" />
</div>
<button type="submit" class="btn btn-primary">Reset password</button>
</form:form>
</div>
</div>
<%#include file="includes/footer.jsp"%>
My reset-controller:
[imports]
#Controller
#RequestMapping("/reset-password/{resetPasswordCode}")
public class ResetPasswordController {
private final UserCommandService userCommandService;
public ResetPasswordController(UserCommandService userCommandService) {
this.userCommandService = userCommandService;
}
#GetMapping
public String forgotPassword(Model model){
model.addAttribute(new ResetPasswordForm());
return "reset-password";
}
#PostMapping
public String resetPassword(#PathVariable String resetPasswordCode, #Validated ResetPasswordForm resetPasswordForm, BindingResult result, RedirectAttributes redirectAttributes){
if (result.hasErrors()) {
return "reset-password";
}
try{
userCommandService.resetPassword(resetPasswordCode, resetPasswordForm.getPassword());
MyUtils.flash(redirectAttributes, "success", "Password was changed");
return "redirect:/login";
} catch (NoSuchElementException e) {
result.reject("Url is invalid");
return "reset-password";
}
}
}
The Resetpasswordform
package com.learningspring.springdiproject.dto;
import constraints.Password;
import constraints.RetypePassword;
#RetypePassword
public class ResetPasswordForm {
#Password
private String password;
#Password
private String retypePassword;
public String getRetypePassword() {
return retypePassword;
}
public void setRetypePassword(String retypePassword) {
this.retypePassword = retypePassword;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
properties file
spring.mvc.view.prefix= WEB-INF/jsp/
spring.mvc.view.suffix= .jsp
spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE
spring.datasource.username= spring
spring.datasource.password= spring
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.javax.persistence.validation.mode= none
Finally 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.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.learningspring</groupId>
<artifactId>springdiproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>springdiproject</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-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</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>
<version>1.2</version>
</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-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.4.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
I am pretty sure my pom and controller are right, since I can't see a difference between this controller and my other controllers.
Note: Password and Retype password are just custom constraints, that check, the size of the password and if the two passwords of the form math an such.
I think somewhere, the Viewcontroller messes up and puts the prefix in there. But I could not find out where that may come from. Others with the same problem didnt have jasper in their pom or the wrong folder structure, but I double checked those errors.
Try to change the following property to start with a /
spring.mvc.view.prefix= /WEB-INF/jsp/
This will allow spring to search into subfolders of your webapp/WEB-INF/jsp path.

Validation not working Spring Boot, Spring in Action excercise

I am following along with a chapter exercise in Spring in Action the chapter goes through validation but even when I POST the forms with empty input it does not return any form of validation errors! No matter what I do I cannot trigger a validation error response, the form is just accepted as it is completely empty.
Full project # https://github.com/AdrianLarssonGit/tacoworld/tree/master/tacoworld
Below is what I assume is the relevant code:
OrderController.java:
package com.tacoworld;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.tacoworld.TacoOrder;
#Slf4j
#Controller
#Validated
#RequestMapping("/orders")
public class OrderController {
#GetMapping("/current")
public String orderForm(Model model) {
model.addAttribute("tacoOrder", new TacoOrder());
return "orderForm";
}
#PostMapping
public String processOrder(#Valid TacoOrder tacoOrder, Errors errors) {
if(errors.hasErrors()) {
return "orderForm";
}
else {
log.info("Order submitted: " + tacoOrder);
return "redirect:/";
}
}
}
orderForm.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>
Taco Cloud
</title>
<link th:href="#{style.css}" rel="stylesheet" />
</head>
<body>
<form method="POST" th:action="#{/orders}" th:object="${tacoOrder}">
<h1>Order your taco creation</h1>
<img th:src="#{/images/startSplash.jpg}" />
<br>
<a th:href="#{/design}" id="another">Design another taco!</a><br/>
<h3>Deliver my taco to...</h3>
<label for="deliveryName">Name: </label>
<input type="text" th:field="*{deliveryName}" />
<span class="validationError" th:if="${#fields.hasErrors('deliveryName')}" th:errors="*{deliveryName}">TEST Error</span>
<br/>
<label for="deliveryStreet">Street address: </label>
<input type="text" th:field="*{deliveryStreet}"/>
<br/>
<label for="deliveryCity">City: </label>
<input type="text" th:field="*{deliveryCity}"/>
<br/>
<label for="deliveryState">State: </label>
<input type="text" th:field="*{deliveryState}"/>
<br/>
<label for="deliveryZip">Zip code: </label>
<input type="text" th:field="*{deliveryZip}"/>
<br/>
<h3>Here's how I'll pay...</h3>
<label for="ccNumber">Credit Card #: </label>
<input type="text" th:field="*{ccNumber}"/>
<br/>
<label for="ccExpiration">Expiration: </label>
<input type="text" th:field="*{ccExpiration}"/>
<br/>
<label for="ccCVV">CVV: </label>
<input type="text" th:field="*{ccCVV}"/>
<br/>
<input type="submit" value="Submit order" />
</form>
</body>
TacoOrder.java:
package com.tacoworld;
import java.util.List;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.CreditCardNumber;
import java.util.ArrayList;
import lombok.Data;
#Data
public class TacoOrder {
#NotBlank(message="Delivery name is required")
private String deliveryName;
#NotBlank(message="Name must be at least 5 char long")
private String deliveryStreet;
#NotBlank(message="Name must be at least 5 char long")
private String deliveryCity;
#NotBlank(message="Name must be at least 5 char long")
private String deliveryState;
#NotBlank(message="Name must be at least 5 char long")
private String deliveryZip;
#CreditCardNumber(message="Name must be at least 5 char long")
private String ccNumber;
#Pattern(regexp="^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$",message="Wrong pattern MM/YY is needed")
private String ccExpiration;
#Digits(integer=3, fraction=0,message="Invalid CCV")
private String ccCVV;
private List<Taco> tacos = new ArrayList<>();
public void addTaco(Taco taco) {
this.tacos.add(taco);
}
}
I am using Spring Boot so have not done much of POM editing except for trying to solve this particular problem, I attach it here anyway for reference:
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.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tacoworld</groupId>
<artifactId>tacoworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tacoworld</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>16</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Removing the whole POM, shutting down Eclipse then regenerate the POM through Spring Boot seems to have solved the problem.
Do not know if it was the POM or Eclipse who acted up but now it does indeed work.

Spring boot controller not returning the jsp page

EDIT : Below is the LatherupApplication Application class:
package latherup.com.latherup;
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(scanBasePackages = "latherup.com")
public class LatherupApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(LatherupApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(LatherupApplication.class, args);
}
}
Below is my home controller :
package latherup.com.latherup;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/home")
public class HomeController {
#GetMapping("/home")
public String navigateToHomePage() {
return "home.jsp";
}
}
Below is the pom.xml file :
<?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>latherup.com</groupId>
<artifactId>latherup</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>latherup</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>13</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap-datepicker</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
</dependencies>
<build>
<!--plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins-->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Below is the home.jsp :
<html>
<head>
<title>Welcome</title>
<link href="webjars/bootstrap/3.3.6/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<div class="container">
<table class="table table-striped">
<caption>Your todos are</caption>
<thead>
<tr>
<th>Description</th>
<th>Target Date</th>
<th>Is it Done?</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr>
<td>Todo 1</td>
<td>10/12/2017</td>
<td>No</td>
<td><a class="btn btn-warning" href="/edit-todo">Edit Todo</a></td>
<td><a class="btn btn-warning" href="/delete-todo">Delete Todo</a></td>
</tr>
</tbody>
</table>
<div>
<a class="btn btn-default" href="/add-todo">Add a Todo</a>
</div>
<script src="webjars/jquery/1.9.1/jquery.min.js"></script>
<script src="webjars/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</div>
</body>
</html>
The controller is returning String "home.jsp" instead of the page. I have added all the dependencies but not sure what is the problem. Is the problem with the versions of dependencies? If Yes, how can I decide on how to choose the versions that are compatible with each other. I keep facing this problem. Sometimes it works and sometimes it doesn't. Please guide me on this as I am a beginner.
EDIT :
Below is the image of project structure :
Application.properties :
spring.mvc.view.prefix=/LATHER-UP/jsp/
spring.mvc.view.suffix=.jsp
logging.level.org.springframework.web=INFO
You have defined spring.mvc.view.suffix = .jsp
So your controller should return home not home.jsp
#Controller
#RequestMapping("/home")
public class HomeController {
#GetMapping("/home")
public String navigateToHomePage() {
return "home";
}
}
You are using RestController for returning the JSP. Use Controller annotations for working on view part.
Read more about it here Controllers
I think you deploy in a web container, to do this you should use SpringBootServletInitializer in your main class, This binds your application's Servlet, Filter, and ServletContextInitializer to the runtime server, which is necessary for our application to run:
#SpringBootApplication(scanBasePackages = "com.baeldung.boot.jsp")
public class SpringBootJspApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootJspApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootJspApplication.class);
}
}
And you should not use #RestController in the controller for jsp view, It should be #Controller, like this:
#Controller
#RequestMapping("/book")
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
#GetMapping("/viewBooks")
public String viewBooks(Model model) {
model.addAttribute("books", bookService.getBooks());
return "view-books";
}
}
Please see this spring boot with jsp section here
try this out
#RestController
public class HomeController {
#RequestMapping("/home")
public ModelAndView navigateToHomePage() {
ModelAndView mv = new ModelAndView("home.jsp");
return mv;
}
}
and while using this remove the suffix and prefix from application.properties

Jar file not working in target folder but working in project folder

When I run the project in STS, it's working fine. All the pages in the webapp folder are loading in the browser. But when I build the project and run the JAR file (folder: D:\SpringBoot Projects\DemoExample\target) and go to the page URL, I'm getting Whitelabel error.
In another project I used spring security- In that project the login page is loading fine, but all the JSP pages in the webapp folder are not loading just like the above example.
While trying to solve this problem, I moved the JAR file from target folder to project folder (D:\SpringBoot Projects\DemoExample) and again ran the JAR file, now the JSP pages are loading fine. The JSP pages are only loading in that folder, if I moved the file to another folder, the pages are not loading.
I want to make sure that I can run the JAR file from any folder.
POM File:
<?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.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.project</groupId>
<artifactId>DemoExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>DemoExample</name>
<description>Project</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-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>9.0.37</version>
</dependency>
</dependencies>
<build>
<outputDirectory>${basedir}/${target.dir}/classes</outputDirectory>
<testOutputDirectory>${basedir}/${target.dir}/test-classes</testOutputDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Main Class:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoExampleApplication {
public static void main(String[] args) {
SpringApplication.run(DemoExampleApplication.class, args);
}
}
Controller:
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
#org.springframework.stereotype.Controller
public class Controller {
#RequestMapping("/")
public String home() {
return "home.jsp";
}
}
JSP File:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Hello
</body>
</html>
Project Structure
Running Jar file in target folder
Result after running Jar file in target folder
Running Jar in project folder
Result after running Jar file in project folder

"Circular view path would dispatch back to the current handler URL." when using Spring Boot and Thymeleaf

When using Spring Boot and Thymeleaf, when trying to accessing the /home URL I am getting the following:
ServletException: Circular view path [home]: would dispatch back to the current handler URL [/home] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
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.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>watchlist</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>watchlist</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-thymeleaf</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
main/java/com.demo.WatchlistApplication.java:
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class WatchlistApplication {
public static void main(String[] args) {
SpringApplication.run(WatchlistApplication.class, args);
}
}
main/java/com.demo.controller.HomeController.java:
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class HomeController {
#GetMapping("/home")
public ModelAndView home() {
return new ModelAndView("home");
}
}
main/resources/templates/home.html:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width = device-width, initial-scale = 1, shrink-to-fit = no">
<title>Web app</title>
</head>
<body>
<p th:text="'Hello world'"></p>
</body>
</html>
Annotate you controller class "HomeController" with annotation #RestController instead #Controller.
Seems duplicate of Circular View path error Spring boot
For springboot 2.6.0, Try controller:
#Controller
public class HomeController {
#GetMapping("/home")
public String home() {
return "home"; // be same as the template file name (without suffix)
}
}
You should have resources/templates/home.html.
Make sure the spring-boot-starter-thymeleaf has been downloaded successfully.

Categories