2

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.

Lukas
  • 51
  • 6

1 Answers1

2

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.

Panagiotis Bougioukos
  • 15,955
  • 2
  • 30
  • 47
  • Unfortunately that doesnt do the trick. If i change the format, none of my jsps are found. Even if i change the prefix to the template folder. In my pom I explicitly state, that packaging should be war. So I don't think thaths the problem source here. It should help anyone that packages as jar though. As it turns out, something might be hardwired in Spring to only look for jsps in webapp, according to this comment https://stackoverflow.com/a/48319098/16522008 – Lukas Jul 25 '21 at 15:17
  • Can you share you code on some github repo and share the link here? – Ajay Kumar Jul 25 '21 at 16:06
  • That did the trick. I should really look into paths more. It's hard to find those small errors, like missing '/'. Thanks a lot. – Lukas Jul 25 '21 at 16:32
  • @Lukas you can always upvote if answer has helped you solve the problem ;) – Panagiotis Bougioukos Jul 25 '21 at 16:36