Search code examples
springspring-mvcthymeleaf

Spring MVC Thymeleaf absolute view ID `/view` behaves inconsistently


I had a simple Spring MVC application with Thymeleaf. I had a controller mapped to /foo/ and it would delegate to a view /bar/view using redirect, so its POST method would return redirect:/bar/view. This worked fine in my IDE, from a JAR file, and from a Docker container.

I did some refactoring and remapped the controller to /view. Then I moved my view implementation from templates/foo/view.html to templates/view.html. And instead of sending back redirect:/bar/view, I sent back /view. This continued to work fine in my IDE (Eclipse EE 2023-03 on Windows) with Spring DevTools installed.

However it would fail running from the JAR, saying that it could not find /view. I double-checked everything, and finally just discovered that it will now only work from a JAR file if I return view for the view, and not /view.

Can someone tell me why this inconsistency exists, and point me to some documentation that covers this? Why can't I return /view as a view ID? But why does returning /view work in my IDE, but not using java -jar …? And finally, why does redirect:/bar/view work with an absolute view path, but not /view? I'm not arguing which way is better; I'm just wondering why the behavior is inconsistent, and wanting to know where this is documented.


Solution

  • It's good to start with how Spring Boot resolves the view names.

    When you return a view with a leading slash /view then Spring treats it as an absolute path and looks for the view in the root directory of your app.

    If you are using view without a leading slash view then Spring treats it as a relative path and looks for the view from the current directory.

    Why then IDE works?

    Because IDE sets the working directory to the root of your project.

    Why then JAR doesn't work?

    It's because JAR sets the working directory to the directory where the JAR file contains.

    Why does redirect:/bar/view work?

    Redirect make a new request to the server, and then resolves the view name using the same rules as before.

    It's good to use relative paths to prevent ambiguities.

    Some information you can find Spring. Views and resolving them